Hacker News new | past | comments | ask | show | jobs | submit login
Featherweight Go (arxiv.org)
252 points by 4ad 39 days ago | hide | past | favorite | 160 comments

There's an upcoming talk by Philip Wadler on this paper on June 8 - http://chalmersfp.org/

YouTube channel where the talk will be streamed live - https://www.youtube.com/channel/UCiGOzKde1rlvzEB7J73gvrQ

From the conclusion:

  Featherweight Go is restricted to a tiny subset of Go.  We plan a model
  of other important features such as assignments, arrays, slices, and
  packages, which we will dub Bantamweight Go; and a model of Go’s
  innovative concurrency mechanism based on “goroutines” and message
  passing, which we will dub Cruiserweight Go.
Love the naming!

> Featherweight Go is restricted to a tiny subset of Go. We plan a model of other important features such as assignments, arrays, slices, and packages, which we will dub Bantamweight Go; and a model of Go’s innovative concurrency mechanism based on “goroutines” and message passing, which we will dub Cruiserweight Go.

Required better for mobile.

And desktop, thank you.

Thanks for posting, but next time please cite with >.

This code block is a scrolling nightmare on mobile.

There’s also a generics implementation on a branch of the go repo.

I’m most curious how they perform on compilation speed assuming a big project makes decent use of generics. I doubt golang would merge anything that causes significant slowdown. And I don’t blame them, the only reason I don’t dread TypeScript dev given its slow compile times is you can typecheck async and strip the typing information for the hot reload.

Don't ever try Scala. I work on a mid-sized CRUD application, and everything we need to recompile from scratch it takes 10 minutes. Typescript and Go are amazing in comparison in that department, but I miss the stronger typing of Scala.

>Don't ever try Scala.

Don't ever try C++. I work on a medium-sized low-level C++ application, and every time we need to compile from scratch it takes over two hours on a single core. Even with distributing the compilation out across over a hundred cores the fastest it can get down to is around 20 minutes.

The thing about C++ compilation time is that if you care you can spend the time to optimize it. Our app takes ~40 seconds to compile and run tests on a decent machine (16 cores).

That only works if you can clean up slow-compiling code faster than other people are writing more slow-compiling code.

Or... you set up your code standards to enforce the same constraints. Everyone pitches in and keeps it clean.

This is interesting. What techniques are you using? Pimpl? Custom, non-STL containers?

I find headers with templates are always the problem. So external template instantiation and pre compiled headers can solve a lot of first time compilation slowness.

Pimpl is more for reducing how much you have to change headers forcing a recompile during development. It's also really handy for keeping binary compatibility with published dynamic libraries so that you don't have to recompile dependants.

Don't ever try Rust.

I haven’t used Rust on any significantly sized project. Could you elaborate? Is it only slow to compile release builds?

It is generally slower to compile than we would like. We have and will continue to spend a lot of engineering time improving it. It is often one of the largest feature requests from the community.

Any compiler that's faster than a human brain is a win. More than that is gravy, and thank you for it.

I started learning rust as a quarantine project, and my <5000 line project takes ~10 seconds to do an incremental development build and 1-2 seconds to typecheck

I work with a ~10k line project and it takes 60s to incrementally compile on a Ryen 3990X. Rust is great, but the compile times do need to improve :-)

What do you mean by "incrementally compile"? an addition of a single line of code results in a 60s build? never experienced anything like that, only the first compile is slow for me.

Incremental compilation results are subjective. If you just changed the file with "main" in it and there was nothing else in there, I'd expect it to be faster than changing a file at the bottom of the dependency tree as you then have to recompile a lot more.

Perhaps they're changing some fundamentals of the codebase and (unsurprisingly) the compiler seems slower than you might expect.

Yes, unfortunately, most of my work is on low-level shared libraries and it often wants to rebuild everything.

It's harsh to say this is due C++ fault, more likely due development culture and desire to be cool by using all the new cool features, without understanding benefits vs price. I was running medium-sized C++ project that included full GUI library - everything compiled under 2 minutes (including tests) on a single core.

Formula known for years: keep it simple, minimal template (ab)use and know what you are putting in .h/.cpp files. Cramming everything into headers hoping compiler will inline stuff is a bed time story. Also, your build system will be grateful knowing that every compilation unit is independent as possible; it will take less time to calculate dependencies and will easily distribute compilation across cores, if requested.

Just try Nim. It is fast.

Nim also supports fancy compile-time metaprogramming and templates. What does it do to make itself compile faster than C++ and Scala?

I can't speak to Scala's compile time issues, but for C++ there are few factors contributing to long compile times.

- "module" system based around textual inclusion of header file: essentially the compiler duplicates a lot of effort, reading the same files over and over for each translation unit, and you can't avoid the cost because of the interaction with text macros. That said, C++20 offers a solution through its new module system; it will be interesting to see how much of an improvement this will bring.

- complicated parser requiring contextual information (i.e. information from typing and analysis phases) in order to distinguish between, say, a class object instantiation and function forward declaration (the notorious most vexing parse). Most other languages learned from the syntax mistakes of C++, but C++ had a clear mandate to not break existing C code, so it had no choice but to build what existed.

- C++ template system revolves around a kind of syntactic substitution, where you have a template expression with some type variable, and at the template instantiation site (i.e. every call, not at the definition) you you essentially do template argument deduction yielding concrete type bindings for the type variables, and then your next step is the transform the AST with the template expressions into concrete types, functions, etc. This involves a lot of tree transformations which can be expensive. I think with other languages this is less of a problem in part because the type checking is done at the definition site, rather than at call site. Here again C++ concepts were introduced to address this issue, but as always in C++, it's not all milk and honey.


I thought that was Rust? ;)

I guess the app uses lots of "header-only" libraries ?

how come hundred cores is only speedup of ~6?

On large C++ projects there are usually a ton of steps that can't be perfectly parallelized. Linking is usually single threaded, you might have dependencies that are way less than 100 CPP files. CMake is single threaded and very slow. Lots of projects have custom Python scripts for code generation or whatnot - all single threaded.

Linking in particular. At one stage, due to enabling LTO, our release build alone took over 20 minutes just to link. And linking cannot easily be parallelised (if at all? I'm not familiar with what the state of the art in linkers is).

I believe that ThinLTO does most of its work in parallel and provides most of the benefit of LTO.

Amdahl's law.

Not a law. Haskell can be much closer to linear, performance to cores. It starts banging its head on the last core; the little bit of other work the computer does seems to throw off Haskell's gait. (This is subjective first-hand experience.)

You can only say the alphabet one way, starting from A and ending in Z. Some tasks can't be parallelized. I expect a lot of those cores wait for critical paths to execute.


Mb the ppl who work on that application should invest a little bit more time in learning how to use C++ properly. I know it sounds a bit silly but if you deal with C++ you should learn it first enough to use it in the right way, or just switch to another programming language, Go is a good candidate.

Switching off SBT to Bazel made writing scala so much more pleasant for this exact reason. Builds are 10x quicker, and the caching makes the initial build take 10 minutes, limited only by the speed of your internet connection!

Do you have any workable example? All the examples I tried haven’t worked on latest bazel version.

How many lines/files/classes split over how many targets for that 10 minute build?

I just compiled around 240k lines of scala split over around 200 gradle subprojects with gradle 6.5rc1 and scalac 2.12.11. Limited to 10 gradle workers. Took 4 minutes without the gradle build cache enabled.

What’s the trick to your faster compile times?

If you model your gradle (or bazel, or maven, or sbt) project as many smaller sub-projects, then the build tool can run a pool of compiler processes in parallel. In the case above, the repo I compiled was broken down into 200 gradle sub-projects. Bazel builds tend to be finer-grained still.

Also gradle 6.5 fixes a scala compilation performance regression that was introduced in gradle 6: https://github.com/gradle/gradle/issues/12591

I guess it need not be the case that generics will slow down compilation that much.

Problem with C++ template generics is that they are reinstantiated per type __per compilation unit__.

I think they can

* Use dynamic dispatch liberally - such that one instantiation per object size in order to avoid boxing. That said, I don't know how the experimental generics work. And this will obviously prevent some optimizations, notably escape analysis.

* defer compilation of generic code to the end i.e "just before linking" phase instead of eliminating duplicates at link time.

* Some kind of caching mechanism for generic code such that you `sed` the machine code / plan9 intermediate to replace it with type specialization wherever required - should work if you are willing to sacrifice some optimizations, As majority of time is spent in code generation. On the flip side, Go team can come up with different optimization strategy for that part of code because Go doesn't do many optimizations in current form.

I am no expert on compilers / optimization. But generics will obviously reduce the total code one needs to compile. And combined with some techniques I guess they can control compile times from regressing.

For caching mechanism, there's zapcc (https://github.com/yrnkrn/zapcc) which launches a background server at first compilation, and reuses instantiated template from the server in the following compilation. Sadly this project was discontinued.

Interesting ideas! some comments from a C++ compiler perspective:

> Use dynamic dispatch liberally - such that one instantiation per object size in order to avoid boxing. That said, I don't know how the experimental generics work. And this will obviously prevent some optimizations, notably escape analysis.

I think you're right about optimization: dynamic dispatch is what most of the template users want to avoid

> defer compilation of generic code to the end i.e "just before linking" phase instead of eliminating duplicates at link time.

Pretty cool. Never thought about that, though I believe LTO in gcc/clang might cover this part in some near future, or already had some partial supports.

> Some kind of caching mechanism for generic code such that you `sed` the machine code / plan9 intermediate to replace it with type specialization wherever required

Not sure about this though...not sure if the benefit outperforms the overhead cuz it sounds pretty expensive. But as a similar approach, JIT compilation might be a way.

If TypeScript compile times feel long to you, I hope you never have to work with a poor build system with a truly expensive language. A clean build with 8 cores at work takes around 10 minutes on my machine. Without parallelization it’s almost an hour. And this with explicit rules against C++ templates…

> Whereas most programming languages use nominal subtyping, Go is unique among mainstream typed programming languages in using structural subtyping.

I thought typescript also used structural subtyping? i.e. in typescript I can define:

    interface Stringer {
      String: () => string
    function takesStringer(s: Stringer) {}
And now I can call takesStringer with any class that happens to have a String() method.

This seems to match structural subtyping in go.

Am I missing some reason that this isn't structural subtyping as referred to in the paper? Do they mean to say that typescript isn't a "mainstream typed programming language"?

It absolutely does. It doesn't have any nominal typing at all, so even classes are compared structurally.

I assume they're not considering it because typescript compiles to javascript, so it doesn't have the problem Go faces of how to generate code for its generics. The wording is definitely weird though.

I'm curious on this part, "Although monomorphisation is widely used, we are one of the first to formalise it.", which are other language had formalise as well?

The talk by Philip Wadler is one of the most insightful I have heard : https://www.youtube.com/watch?v=Dq0WFigax_c

In brief, they are following a process of stripping Go to the most basic possible syntax, and then adding generics (Featherweight). Then they will add more features back and build up to the full language, ending with Cruiserweight where channels will be addressed.

The generics proposal builds on interfaces rather than contracts. Wadler sees Go occupying a unique space in terms of supporting "open supertypes" in the sense that in Go we do not have to declare a struct to be of a particular interface type it is automatically derived based on the methods defined on the struct. This allows a proposal which allows Go to be extended tp solve the "expression problem" first defined by Wadler in 98.

I really hope these beautiful ideas turn out to be workable - I am sure Go will gain immensely if they are well thought out.

Fingers crossed: hopefully this is a step towards generics in golang.

Up to now it always seems to have been one step forward, two steps back (or rather "wait another few versions")

The irony of going back to Featherweight Java, done in 2001.

At least some work is being done, even if "This is the beginning of the story, not the end".

I don't think this is so ironic after all.

Featherweight Java is an idealized language, small enough for doing experiments. These experiments often involve the necessity of a formal proof. But being a small language, still capturing the crux of the full language, greatly simplifies the problem space.

Featherweight Go serves the same purpose: find the core. Give the core generics. Then you have a good chance at implementing generics for the full language.

Most languages which end up with type parametrization do so when the language is small and somewhat pliable. Neither Java nor Go did, even though both languages had plenty of prior work in the area. Hence, you have to "reconstruct" a world in which there is such a small language such that your experiments run fast.

I think this just highlights how massive a mistake the Go developers made not including generics from Day 1.

It was a mistake in Java that they corrected with a lot of pain. It is a mistake in Go they are going to correct and most likely with a lot of pain. If they cannot do it seamlessly it may end up being a Python 2/3 platform split.

Those who fail to learn from history are doomed to repeat it.

It's not at all clear that it was a mistake. Go has had eight years of being one of the more successful languages. If they had tried implementing generics right away, it may have taken longer and it's unclear whether Google would have supported the work for so long? Maybe the timing would have been different enough that they didn't succeed, or the lack of experience would have resulted in a design that's worse?

It's also not at all clear that Go will have similar problems as Python did, since the Go team considers backward compatibility important and might approach the problem differently, learning from Python what to avoid.

Counterfactual reasoning is difficult. Learning from history isn't as easy as some make it look.

It was successful due to massive amount of money spent by Google.

Because there were languages that are much better suited for what Go was designed for. To name a few: Erlang (concurrency that is better than Go's, "channels" and types on par with Go with Dialyzer), Haskell (thread concurrency better than Erlang's, channels, transaction memory, etc and types well beyond Go) and many others.

Go was successful despite mistakes.

I'd say the popularity of Go stems from the lack of generics.

No, it doesn't. Go is popular because of the names and organization behind it, as well as the fact that it's useful for a lot of people despite the lack of generics.

Certainly, a lot of people are attracted to Rob Pike's rather idiosyncratic preferences, tastes, and nostalgia for the early days of Unix, which are on display in a lot of Go's design decisions, like the lack of generics. But lots of random people have preferences and nostalgia for all sorts of things; we usually only pay attention to such things when it's a person with a famous pedigree who has them.

The "names and organization behind it" thing is needlessly condescending (not to mention false), and the ability to get things done without generics basically restates David's point.

Was there something in this paper that you felt unfairly treated Rust, the language you represent on these threads? Because otherwise, I can't see what would motivate you to join this thread to snipe.

I'm with David, for what it's worth. Lack of generics has mostly helped me be productive in Go, and the extreme prevalence of generics in every Rust library I deal with has definitely slowed me down a bit. I'm looking forward to generics support in Go, but mostly for what I hope it does to message board threads.

I went out of my way to make the point without condescension. Evidently I didn't succeed, and I'm sorry for that!

Let me put it another way: Virtually all languages that have become popular recently have done so because of the backing of some large organization or another. There was a time when languages like Perl, Python, and PHP could arise out of basically nowhere and become popular. That time is gone, and now languages essentially need organizational backing of some kind to succeed. That was true for TypeScript, it was true for Rust, it was true for Swift, it was true for Kotlin, and it was true for Go. They also benefit from some sort of well-known thought leader, a role that Rob Pike plays well. If you think Go would have gotten popular without having a Google and a Rob Pike behind it, then, well, I don't know what to tell you. I don't think Rust would have been popular either without the Mozilla association.

Or, more succinctly: I see no world in which Go having simple ML-style generics, without typeclasses or functors, would have made it any less popular. Other factors dominate when it comes to success of a programming language. TypeScript, in fact, shows that you can have generics that are more complex than those of Rust and still become wildly popular.

After a week (my first week, to be fair) of hacking on a serious Rust codebase, I'll give you one reason lack of generics might have been a marketing win for Go: I have never appreciated Go's compiler speed more than I do now.

But the bigger problem is just that Rust programmers use generics absolutely everywhere (my early impression is you basically can't avoid it, because of lifetimes), and it simply does make everything harder to understand. I know I'm going to be told that if I buckle down all of this stuff will make sense and I'll be fluent with it, and sure, I managed to grok Alexandrescu C++, too. But adding new layers of indirection everywhere just has to impede comprehension; that's always the tradeoff for parameterizing and indirecting!

The flip side of this is, I've built some fairly serious things in Go --- a compiler, a couple emulators, a disassembler, a symbolic evaluator; not just the server stuff Go is supposed to be good at --- and I have complaints about Go, but almost none of them are its lack of generics.

(There are things I like about Rust! But this isn't the thread for it.)

What are your complaints about Go? I'm curious to know whether they match mine.

- (removed by author; was too aggressive)

Edit: Removed my response. No worries :)

Rereading that comment I do think I was being uncharitable and have removed it.

Reading the esbuild discussion at the time, it definitely read to me as "our language is definitely faster and if you're not getting the same performance you're holding it wrong", but looking at it now I can see how it wouldn't be intended that way.

Regardless, sorry; I think I was projecting some frustrations with the wider RESF on to you.

And for what it’s worth I spend at least as much of my time wishing it had user defined generics as I do enjoying what it does have.

I’ve now resigned myself to wishing it treated its magic generics with proper typing.

A lot of us Go developers would probably say we like Go because "Go is useful" and leave off the rest.

You are right, Go got more initial momentum because it came out of google and had Rob and Ken's names attached to it. But the useful part is why people actually use it.

> Go is popular because of the names and organization behind it

I hear this a lot, but the counterexample is always Dart. Google is behind it, and Lars Bak is definitely not a nobody, yet the language struggled to gain momentum; not until Flutter came on the scene, and it wasn't an official Google project when it started.

Lars gave a talk last year and said the intent was to put dart vm in chrome, then the whole mobile thing happen and there was no room for extra stuff in chrome. https://youtu.be/mPna6D21Eqg?t=480

at least to me, the lack of generics was a benefit. I'm probably not alone :)

And why on earth would you say that?

because it's a breeze to read Golang, due in parts to the lack of generics

Lack of generics just means you have to copy and paste everything, like any time you want to reverse a slice.

    for i := len(a)/2 - 1; i >= 0; i-- {
        opp := len(a) - 1 - i
        a[i], a[opp] = a[opp], a[i]
Actively hurts reading code as you have to credentialize in a code base to begin to be able to file entire code blocks into copy and pasted "idioms".

Without generics you have to hope the stdlib gets a blessed generic function like reverse() one day since you can't build one without rolling your own monomorphization code-gen or a goofball interface{}+cast hack.

For people who supposedly prefer the lack of generics (which seems more like cargo culting or Stockholm Syndrome), no problem. We can just add a config option to golint that prohibits you from using generics. That way you don't need to hold up the rest of us. win-win.

Weird. While you could copy that from the SliceTricks Go wiki page, you could also just use `sort.Sort(sort.Reverse())` which seems to address all of your complaints.

But it uses an interface, which means dynamic dispatch and an allocation most of the time (because IIRC it tends to break the escape analysis).

That's a recurrent issue with Go: you can either have ergonomic tools (with interface and reflection), or performant code (with no allocation) but you generally can't have both at the same time. Sure it's better than scripting language where you need to use another language when you need performance, but it's still kind of sad.

Why does genetics make things that’s for read?

Functions can be given semantic names (I.e. have meaning); block statements cannot.

If writing a function that can take an array or slice of any type of data requires providing a generic argument (I.e. so you can specify that the function returns a slice of the same type of data as it was given), then you can name it "reverse" if it reverses the array, write it only once, and every timr you use it, you read "reverse" and know what it does.

For loops dont have those names, and so have to be rewritten every time you use them. As such, every time you see a for loop, you have to read and parse every statement to see what it is doing, and if it has any unexpected side effects or bugs introduced via copy-paste or what not.

Sorry I meant to say “why do genetics make things harder to read?”. Tbh I can’t tell if you’re responding to that or not

I did misread your post, but I will also say that generics are a double edged sword when it comes to readability. Needing to declare genetic types in function signatures can add irrelevant detail and heavy syntax. For example, look at the interpreter interface in this typescript file:


Granted, genetics don't need to be done that way, but it is among the more common and popular approaches. The type information is tangled up in the implementation, making focusing on either more challenging. Perhaps we need modes for syntax highlighting- one for types, one for implementation?

Except that these kind of experiments contributed to Java generics, being made available 3 years before Go 1.0 was given a green light.

Which is why Go had already a good example to learn from on how not to do language design.

Are you suggesting all new typed languages have generics? What makes you so sure there isn't room in the design space for a typed language without generics?

As much as I like generics, Go's popularity is a success: programmers have spoken, and they value other things more than generics.

Hindsight is 20/20, and even this isn't a commitment to introduce generics in Go.

Go's popularity is due to author's employer.

Both its main influences, Oberon-2 and Limbo had zero traction on the market, and Limbo not only is quite close to Go, it had an whole OS full of the Plan 9 ideas to come along, yet it failed on the market.

Lack of generics has already been publicly acknowldge as problem.

> In three years of Go surveys, lack of generics has always been listed as one of the top three problems to fix in the language.


And yes, there is no place on the 21st century for typed languages without generics, we already have enough of them from the previous century already.

CLU and ML, the first languages to support genericity are from the mid-70's, they are older than C++ and contemporary to C.

I think Go is popular because of its simplicity and fantastic standard library.

It can also feel sometimes like a dynamic language which has attracted people from ruby, python, JS, etc... communities.

You say there's no place for it in the 21st century, yet it already has a place and it doesn't really need generics to continue living.

Thanks to generics and lambdas, Java's standard library includes concurrent mapreduce. Lacking generics, Go's standard library can't even offer https://golang.org/pkg/sync/#Map without sacrificing type safety.

I agree Java streams and concurrent collections are great.

I agree Go cannot offer similar things due to a weaker type system.

I willingly code Go day-to-day. I miss Java streams, and sometimes the codebase is slightly worse due to the lack of Java streams (or equivalent).

I accept a weaker language because I spend less time debating the Right Way to do things (Go is too inexpressive to support a Right Way), and because I can widen my hiring pool from those that know Java, to those that any language, knowing that they can easily pick up Go.

> Go's popularity is due to author's employer.

Why isn't Dart seeing the same type of success?

Because it was dropped on the floor by the Chrome team, which lead to the original team leaving Google, if they had shipped Dartium the outcome would be much different.

Is Dart's lack of popularity in spite of its author's employer, then?

Dart's lack of popularity is indeed in spite of the Google backing. I basically see two reasons. First, though Lars Bak has an impressive pedigree, Strongtalk and V8 aren't as well-known as Plan 9 and Unix. Moreover, rightly or wrongly, Dart had the appearance of "Google's attempt to kill JS", which neither endeared it to Web developers (who were riding a wave of JavaScript hype at the time) nor to other browser manufacturers (who were growing increasingly distrustful of Google's initiatives).

Because it was dropped on the floor by the Chrome team, which lead to the original team leaving Google.

Original Go team did not suffer from this.

> Lack of generics has already been publicly acknowldge as problem.

That's from people who complain because they want Golang to be like Java

It is more people that don't want Go be a plain Limbo remake.

"programmers have spoken, and they"...'ve done quite a lot of work to get the benefits of generics without language support. You can pretty much look at any large Go project (famously Kubernetes) and see a workaround of some shape or form.

Kubernetes has lots of workarounds - I’m not sure generics are the ones I’ve worried about the most.

If I had to write a list of “tools I would have preferred to have”:

1. Perfect serialization libraries - Serde is the gold standard here, and IIRC the macro system from Rust is as important a part of it as the traits part.

2. Mutability of types in shared caches - to build efficient controller patterns you need fast and efficient caches - an immutable type that protects against mutation would have saved a lot of ugly mutation testing code

3. Client library definitions shared across types - we could have reduced a fair amount of boilerplate with generics, although most bugs are in the serialization part these days as types evolve

But most of these are dwarfed by the need to scale reviewer time across hundreds of people submitting PRs that change fundamentals of the code. The simplicity of Go and ability to review stupid, obvious, absolutely critical code is the reason why I love it.

Having a strong way to reduce cleverness has been a godsend. It doesn’t mean cleverness is bad, or I don’t want more tools in Go. But I appreciate that aspect of Go in a way that others may not.

Edit: I have been watching kube-rs mature, but to get the same level of scale and performance we’d have to reproduce the shared index informers and that’s a lot of drudge work to get right. That’s one place where someone motivated could really help Rust become a first place way to extend Kubernetes, which would be exciting.

Hacker News law: In every thread about Go someone will bring up rust.

Don't mind.

The comment you are replying to was written by one of Red Hat's lead kubernetes developers (https://github.com/kubernetes/kubernetes/graphs/contributors).

While k8s's code is atrocious, I wonder if that isn't due to its legacy translation from Java (iirc, it was written in it initially)

Kubernetes had a non-public prototype in Java. None of the code in the main tree even resembles the code from that prototype (I was one of the first non-googlers to contribute).

It’s just ugly because that’s how it evolved after a community formed and that’s what real evolved software looks like. :)

Go is popular because Google enjoys shoving it down our throats not because it is a particularly good language.

Not saying it is a bad language, but it really helps that Go had Google's blessing.

Strange. I get the impression that Google's support for Go is rather half hearted.

Or perhaps Google has many hearts and no one knows exactly how many or where they are at any given point in time :-)

> Go is popular because Google enjoys shoving it down our throats

How exactly is Google "shoving it down our throats"?

Java had generics in 2004 w 1.5. Go didn't come onto the scene until 2012... so more like close to decade.

I dont think expirements are a way to qualify decades of research that went before.

Second what Sun choose to implement was a smaller subset and not that close to Featherweight Java/pizza compiler. It was only generics, not first class functions at the time, nor algebraic types/pattern matching.

Go is a popular language. A common criticism is lack of generics. Go has sought advice from the type theory community. This is the result. What alternative for Go do you know of that doesn't involve going back to 2001 technology?

They could have gone to 2001 technology way back. The Go FAQs say ->

> " We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it."

I mean if you are going to use 2001 technology, you could have found it long back.

Yet, they acknowledged it was a mistake not to consider them.

> In three years of Go surveys, lack of generics has always been listed as one of the top three problems to fix in the language.


By the way, they could have gone to 1974 (CLU), 1973 (ML), 1983 (Ada), 1986 (Eiffel), 1988 (Modula-3), 1990 (Sather & BETA), 1998 (C++), 2007 (D), 2009 (Java & Delphi).

These are just the most well known examples, CS literature in SIGPLAN and IEEE has plenty more to choose from. I bet Google employees can afford the respective subscriptions.

When there isn't any political willingness, there isn't anything to be found.

You're commenting on a paper by expert programming language theorists describing a design that is both complex and (in some aspects) novel. Almost certainly an element of getting these people to work on it is Go's existing popularity, it's mentioned in the second sentence of the paper.

If I understand you right, you are suggesting that instead of doing what they are doing now, they should have just used an existing design from your list, right from the beginning?

Is there any specific design from your list that you think would have been good to use in Go? Or, do you think it would have been better to have a less-capable generics implementation available right away instead of a more-capable one later?

For example the one you mention the most (Java) requires code duplication to work with 32 and 64 bit floats. I think even the previous proposals that have been rejected for Go have at least had that ability.

Yes, right from the beginning. Java isn't the only language to chose from.

It’s hard for me to believe that it is as simple as you suggest, considering the large amount of work put in by the Go team already, and the even larger amount of work put in by other programming language implementors to eventually arrive at various (different) design points. Work which often takes many years like C++ concepts.

Not to mention the open invitation for concrete proposals on how to add them Go.

You might find this post by one of the Go team members interesting:


As proven by the lack of progress, that invitation has just political value, it allows posts like yours when these discussions take place.

For example, while Valhalla has taken several years so far, OpenJDK team has experimental builds that you can go and play around with value types in Java.

Where are the experimental builds for generics support in Go?

> For example, while Valhalla has taken several years so far, OpenJDK team has experimental builds that you can go and play around with value types in Java.

Actually Valhalla is pretty interesting to think about. For what I'm currently working on, the inability to have a list of points without individually heap-allocating each one makes a language much more of a non-starter than the lack of user-defined parameterized types does.

Even back when Java was invented, there was plenty of prior art (going back decades) about efficiently representing a list of points in memory. Probably most of its predecessors could do it. Yet Java has lacked this basic ability for 25 years.

I even expect that when they eventually implement it it will work similarly to other popular languages, compared to Go which seems to be drawing on more recent developments (like concepts etc) for its generics design.

Despite this, I don't accuse the Java team of political machinations every time the topic comes up. Mainly because I don't believe that to be the case. Maybe they've prioritized a critical feature for me lower than I would like, but it seems like a substantial amount of work to implement because (like generics) it interacts with other language features in a complex way and (like generics) once they ship a design they will be stuck keeping backwards compatibility with it basically forever, so they only have one chance to get it right.

The difference being that Java teams deliver language improvements and go on the stand acknowledging where to improve and setting roadmaps, Go not so much.

Even stuff like error handling improvements and type alias were almost shot down.

> The difference being that Java teams deliver language improvements

Sure, I think it's fair to say they've focused a lot more on implementation and library changes and not language changes up until recently. Things like rewriting the compiler from C, improving code generation / escape analysis / GC, more platform / architecture support, improving the standard library, getting a reasonable package manager, etc.

So it seems a little premature to read some secret anti-generics stance into it (and it not just being a matter of priorities) since there were all these other areas that they were also way behind Java in.

After package management was in generics started showing signs of life again, so it all seems reasonably consistent with the Go team just wanting to clear other stuff off their plate first before tackling it. Hopefully we see it in a similar timeframe to major Java/C++ features now that it's being worked on more.

If there's any silver lining the actual proposals seem pretty ambitious, seems like they want to enable a lot more than just new type safe collections if they add the feature.

This actually exists. There’s a go playground earlier in this thread worth generics support

Which apparently hasn't been updated since August, 2019.


So this is the prototype used at the GopherCon talk.

Huh, if there are so many languages to choose from then people can choose one of those. Go will die its natural death. Where is the problem?

The problem is that like with JavaScript in the browser, some of us do have to put up with Go when dealing with k8s, even if we rather not.

Secondly, I also kind of like Go, just see it as lost opportunity to have been with little more than a C like type system, even C has some genericity support in the meantime.

And whatever gets out of it, will be rather clunky as proven by late adoption in Java.

They weren't convinced at the time. Now they feel compelled to act. How is this political?

They have been saying that for years now. Yet nothing to show other than an half finished code repository.

Sorry someone forgot to tell them that they should follow your priorities.

On another note, every other Go thread has you and @pcwalton bashing Go. Makes me wonder if Go's success causes some sort of discomfort in some people. It's almost religiously guaranteed to have you both regurgitation the same crap over and over.

Jesus! They are building software for themselves that prioritize the things they want and need, not some rando commenters on social media. They have every right to go about things their own way and succeed or fail based on that. So far it seems to be working and a lot of people are quite happy with the results (myself included). You seem to be particularly upset by this. Why is it so terrible?

What about the irony of pjmlp dismissing something because it's based on an obscure language going as far back as 2001? :-)

Except that Java isn't obscure and experiments like Featherweight Java contributed to Java generics final design, introduced in November 2009, 3 years before Go 1.0 was released.

What about that then?

My comment was not meant as criticism, I just thought it was nicely ironic.

But I guess you're actually consistent: you often lament about people ignoring or reinventing approaches that proved themselves in older languages. Here are people that actually take clues from one such language, and you lament that they didn't do it earlier. I see now that it's not really ironic. Rather, you're seeing the glass half empty while I was seeing it half full.

I would be happy if this was their first attempt, sadly I have lost count how many times the team has published such studies with zero outcomes.

While I am sure Java will get value types, it already has had several experimental releases and the features have been incrementally integrated, after the switch to 6 months release cadence, I am not so sure in regards to Go.

All we get is a source code repository full of comments showing how much is left to be done, if ever. Untouched since last August.


It only strengthens your point but Java 5 was actually released way earlier, in '04.

Thanks, it is what happens when one doesn't check dates. :)

Why is that ironic?

The syntax really makes me think to Zig - https://ziglang.org/documentation/master/#Introducing-the-Co.... I'd be curious to know if the authors of this paper have looked at it.

Info on the current implementation of generics in Go how to tryout the generics branch parhamn mentions is available at https://blog.tempus-ex.com/generics-in-go-how-they-work-and-...

That's the previous design based on contracts.


This one seems to be the new FGG one.

That's from the previous generics proposal, substantially different from this one.

This is the intersting discussion. What of the two proposals will receive the Go authors blessing? Isn't the arxiv version just a Guerilla attempt?

The former proposal was made by 2 members of the Go core team. And they are also in the team of the latter proposal. So, no, the first proposal wasn't good enough for the Go authors and the new proposal is in no way a guerilla attempt.

Thanks for clarification. I followed the discussion in https://go-review.googlesource.com/c/go/+/187317 loosely, thought that this is the only way to go and wasn't aware of a second investigation stream.

Go generics without introducing contracts! This is exactly what I was hoping for!

For anyone interested in seeing what's possible with Generics in Go - Here is an online playground that uses the browser-based playground and a WASM compiler to run the generics proposal (in browser).

The example includes a simple generic `Filter` function


Is that a jab at Haskell in the very first paragraph?

> Today [Go] sits at position 12 on the Tiobe Programming

> Language Index (Haskell sits at position 41).

One of the authors, Philip Wadler, contributed heavily to the design of Haskell. So I presume it's friendly joking.

Authors wants to bring types to where people are. Simply justifying their work.

PLZ don't. Let's keep it C-like

May be an attempt to silence the Rust-fanbois because of the touted old-fashionism of Go. So let's sprinkle some ML topping an be good.

Thanks for reminding me how the rampant abuse of nearly unreadable mathematical notation for things that can be easily expressed in concise natural language contributed to (voluntarily) shortening my academic career.

But more seriously, it's interesting how this produces publications before actual implementations.

Closer to logic. There is a straightforward rewrite into prolog if you want a program. Or one of the proof assistants.

The notation is abused though. Try looking up some of the work by Guy L. Steele in the recent years.

Just to clarify: Steele has been documenting, not perpetrating, the abuse. See for example


> Closer to logic. There is a straightforward rewrite into prolog if you want a program.

Journal papers usually don't get rewritten into Prolog or fed into proof assistants. They're read by human beings. I've long suspected (and colleagues used to "joke" about it) that excessive use of mathematical notation is just employed to impress and/or confuse peer reviewers into just accepting the paper instead of trying to comprehend it first.

Stop trying to justify your own ignorance.

The sequent calculus is great—I am far from an expert and for many papers I can skip the text at first, read the sequents, and then just go back to the prose only if I have specific questions. No prolog conversion needed.

As programers, we should be able to read, not just write, formal languages, and appreciate the value of the precision they provide.

> Stop trying to justify your own ignorance.

I am not ignorant. I tried to rationalize this in the beginning too. It's just hostile towards the reader.

> As programers, we should be able to read, not just write, formal languages, and appreciate the value of the precision they provide.

We should also be able to see where they are appropriate and where not.

It's not hostile towards this reader (me). It's perfectly appropriate. I would be annoyed if they weren't there.

Well, some journals have demanded proof assistant-level proofs of the work they present. This helps the rigor of the notation a lot since you can't cheat on the proof assistant, and if you confuse it, you are in trouble :)

The problem is that getting the notation right is actually quite hard. People write, to the best of their effort, to make the description succinct and understandable. But the notation is pliable, in the same way much mathematics is written: it isn't as rigorous as we would like.

Writing the same thing in regular prose is much much harder and there are many more ways things can go wrong.

So the state-of-the-art demands formal proof which can be verified by a machine. And it shows in the precision of the notation, which often leaves little to no room for wrong interpretation.

If you want to reason about low level compiler optimizations, learn some assembly language. If you want to reason about type systems, learn how to read basic typing rules, it's not complicated.

Sometimes planning before implementing is a good thing, or does even language design need to be agile™?

What is this gibberish? I was fluent in 68k assembly 30 years ago and teaching compiler construction at university 25 years ago. Were you trying to make a point?

> The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety.

Not sure what real problem this is solving. In practise you don't just add new cases, you delete some cases, and you re-add different cases later. Two different people might add two different cases in parallel with each other. Oops, now you have to re-compile anyway.

Suggestion: While your paper is very intellectual and I laud that, perhaps what would work better for mass uptake is to create your own programming language around the concepts you propose, and let people try that language. You could call this language "Featherweight Go" if you wish, but perhaps it would be better to call it something else entirely, and simply state that that this new language was inspired by Go.

This choice comes with potential business, legal, and other ramifications, for example, should Google get all of the benefit, in terms of fame, goodwill, users and other intrinsic bonuses from the work you've done; or could you profit (if that was your goal) if you were to create your own company around this new language?

You see, that's what I mean by potential business and legal issues.

Oftentimes, people who are employed by other people work extremely hard on academic pursuits, such as academic papers, yet their work is never adequately rewarded, compensated, or even appreciated.

Which is why I suggest you create your own language and possibly your own company around that language. Because otherwise you'll never know nor understand the true economic value of what you've created, and you might spend an eternity trying to convince people who are of lesser intelligence to read your paper, whereas they could be using, downloading, telling their friends about the great new language you created; and maybe even paying you money, if you played your cards right...

Note that I am not suggesting you go this route (it's your decision, maybe you just want to bring better free open source software to the open source community and that's highly laudable), all I'm saying is, you might be on your bed on your 85th birthday, and you might look back at your life, and you might wonder "boy, I wonder what would have happened had I tried to start a company around this set of ideas; I wonder what would have happened if I had taken the road not travelled.."

That's all I'm trying to say...

Nothing more, nothing less.

Your choice.

Make it wisely.

Your paper shows tons of intellect.

What are you talking about... Two members of the Go team are on the author list.

If I were them, I'd leave Google and start my own programming language company. I can't speak for them of course, but that's what I would do if I were in their position.

You appear to have entirely missed the point of the paper. This is an exploration of a mechanism for implementing generics in Go in the future. It's not a proposal for a new programming language.

The "Featherweight Go" referred to in the paper is simply a tiny subset of the Go language itself that's being used as a framework for formalising the mechanism they're proposing could be used.

that's one hell of an off-topic comment if I've seen one

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact