Live data from Hacker News

Notes on the Go2 Generics Draft

jmoiron.net

21–30 of 116 posts

Re: Notes on the Go2 Generics Draft

#21
post #5

The author makes some interesting arguments, but they are all predicated on the idea that generics are somehow hard to grok or use? Having helped teach Java to many people with less than a year's programming experience at university, I refute this. Bear in mind we're hardly talking about higher kinded types here. Generics are a simple abstraction over a lack of type information which allows you to write and maintain…

I keep hearing people say things like "the Go team are changing their position" but I think what a lot of people missed is that the Go team were never against implementing generics in version 2. Quite the opposite in fact as they actually often said it was a consideration for Go v2. What they repeatedly opposed was rushing generics into a v1.x build as that could break things. The real issue is that many of the "hate…

> hate using that term but it really was largely just individuals who decided that didn't like Go from the outset anyway so weren't exactly day to day Go developers

I'm a day-to-day Go developer and maintain some of the most widely used Go projects out there. While I understand their wish to do things "slow and steady" there were several other missteps and double-downs by the language designers that left me with a bitter taste in my mouth.

Not to mention that Go was sold as a systems programming language, but my last 5 years of experience with the language (developing container runtimes -- which are the most canonical example of systems program you can come up with these days) tell me otherwise.

Re: Notes on the Go2 Generics Draft

#22

Yet another language tries to bolt on generics after the fact and finds that doing so results in awkwardness. Note to language designers: if you are creating a general purpose language, you will eventually need to add generics. You can either do it right at the beginning, or else you have to bolt it on at the end. Rust gets kudos in this regard for having well designed generics from the beginning.

Kudos also to prior art, such as the ML family of languages, which Rust derived inspiration from :)

Re: Notes on the Go2 Generics Draft

#23
That's elaborate. More elaborate than expected for Go.

I was expecting something more like explicit parameterized types. Go already has those - maps and channels are parameterized types. You just can't define new parameterized types. Extending Go to allow those would be a smaller step. That doesn't get you overloaded functions, though.

The designers of this wanted the ability to define a new function F(T x) which works for any T upon which a known list of functions can be applied. Then they wanted that to work for separate compilation. So there's all that "contract" stuff to carry the info about what F needs from T. Seems clunky. It violates the rule "You should never have to tell the computer something it already knows." It's clear how the constraints they set upon themselves lead there, but it's still clunky.

This design does not support template metaprogramming or any other form of compile-time programming.

Whew! That's a relief.

"We expect that most people will not write generic code themselves, but many people are likely to write packages that use generic code written by others."

In other words, maybe it is a little too complicated.

Re: Notes on the Go2 Generics Draft

#24
I'm glad I'm not the only one sad to see generics invading a perfectly good language.

Programmers love generics because they enable higher-order abstractions, and programmers love abstractions -- code that isn't DRY is like an itch we need to scratch. Programmers also hate special cases, because they feel restrictive and inconsistent: I recall quite a few people protesting that Go's 'range' keyword shouldn't be restricted to a handful of built-in types, but rather should support any type implementing an Iterator interface.

But Go was not designed to be perfectly consistent or to enable high-order abstractions. It just aims to be productive at scale, and that often means restricting the programmer. Go tries to be non-magical, and sadly that can take much of the whimsy out of programming. You can't chain together operators in point-free style, or add a property to every 'Object', or directly increment a string, or anything like that. In other words, it's a terrible language for code golfing. But that sort of code has no place in a production environment anyway. It's "clever" code that gives the programmer a little dopamine hit when he writes it, and his co-workers a headache three months later. Those are misaligned incentives.

So I worry about generics because they let you abstract with wild abandon. They let you inject a little magic. And I fear that programmers will be seduced by their love of magic, and I'll be the one who ends up paying the price.

Re: Notes on the Go2 Generics Draft

#26
post #25

Can someone explain in terms to someone who hasn't really used a static typed language what "generics" are? I've only used javascript and ruby.

In a static language, functions, classes, and types are often parametrized by other types.

For example, with a function: imagine you wrote a `sum(array)` function. In Ruby that's not a problem, because array can contain any types, as long as they support the + operator (aka duck typing). Any function can also return any type of object.

In a static language, however, an array that holds floats has a different type than an array that holds integers or an array that holds strings. The return value of the function sum() will also be different, depending on the type of the array, because if it's an array of floats, the sum will be a float.

So generics allow you to sort of implement duck-typing in static language:

T sum(array) // Pseudocode

Now the sum function will take an array of any type T, and return a result of the same type T.

Similar idea for classes and other types. The classic example is a container. A linked-list in Ruby can contain any type or mixture a types, since the language is fully dynamic. However, in a static language, a linked-list of strings has a different type than a linked-list of ints. So you write something like (pseudocode):

class List { T head_val() { return head.val; } }

Now you write the List class once, and use it for any type T, so it's DRY when you may have any number of types T that your program stores in a list.

Re: Notes on the Go2 Generics Draft

#27

I'm glad I'm not the only one sad to see generics invading a perfectly good language. Programmers love generics because they enable higher-order abstractions, and programmers love abstractions -- code that isn't DRY is like an itch we need to scratch. Programmers also hate special cases, because they feel restrictive and inconsistent: I recall quite a few people protesting that Go's 'range' keyword shouldn't be restr…

This. Worked with large C# code bases that were full of leaky abstractions using generics.

Programmers thought of ever edge case, until you found that edge case that wasn’t covered in the long chain of inheritance of generics.

Point being, I agree with you, I know Go doesn’t have inheritance like C# but I’m pretty sure we, as a community, we’ll find a way to complicate everything Go related.

Re: Notes on the Go2 Generics Draft

#28
post #25

Can someone explain in terms to someone who hasn't really used a static typed language what "generics" are? I've only used javascript and ruby.

Consider this function signature:

func SomeAdditionFunction(arg1 int, arg2 int) { fmt.Println("Sum:", arg1 + arg2) }

This function will only accept a pair of integers. In order to perform addition on floats or int64s or any other number type, you would need a separate function.

Go has the concept of an empty interface (interface{}) which can accept any type. But this is not really a generic because you have to assert that it is a specific type in order to be sure what it actually is at runtime. This function for example, will not compile:

func SomeAdditionFunction(arg1 interface{}, arg2 interface{}) { fmt.Println("Sum:", arg1 + arg2) }

But this will:

func SomeAdditionFunction(arg1 interface{}, arg2 interface{}) { fmt.Println("Sum:", arg1.(int)+arg2.(int)) }

In a language like Java, I could write this function to accept any type for which the + operator is valid, and it would still be type safe at compile time. I would not need to assert the types like I did above.

Re: Notes on the Go2 Generics Draft

#29
I’m a fellow generics pessimist. Having come to Go from Java some 6 years ago I initially found the lack of generics a curious, sometimes frustrating omission.

After years of using Go daily and reading a long succession of posts on the go-nuts mailing list wherein Rob Pike, et al, repeatedly and staunchly defended the lack of generics as necessary – even beneficial – in the pursuit of designing a small, readable, coherent language, I’ve since come to believe that decision was entirely correct.

Perhaps nobody technically promised there would never be generics in Go’s future, but it’s undeniable that they run contrary to those stated design goals. As currently proposed, they will add considerable complexity to the language in exchange for questionable benefit.

I’m not sure the world needs another kitchen-sink language that eschews clarity for the unrestrained addition of features. If you want that, there are already plenty of options for you.

Re: Notes on the Go2 Generics Draft

#30
It's impossible to defend the lack of generics in golang in the face of the fact that two of the larger open source projects both invented their own generics implementations.

https://medium.com/@arschles/go-experience-report-generics-i...

https://github.com/google/gvisor/blob/master/tools/go_generi...

Post reply on HN