1. 24

This has gotten some heated discussion elsewhere, but mostly on the really general, recurring debate about Go and generics, and related flamewars like whether Go’s designers are retrograde luddites or else wise pragmatists. The documents here are more interesting than that debate, which is why I think they’re worth linking. :)

Despite the title, it’s more of a documentation of four unsuccessful attempts work through how to add generics to go. The author would like to add generics to Go (and I believe still does), but in the four sub-documents linked at the end, each works out a different specific approach to making it work, and runs into various bits of trouble. Some of the details about how features interact and the difficulties that come up are interesting imo.

  1.  

  2. 7

    I think the majority of Go programmers would like to see generics. I still haven’t seen a really clean proposal which everyone’s happy with though. Does anyone know of a good proposal?

    1. 5

      seems i’m in the minority ;) i still think that it’s easier to just copy some code (or let it be generated!) than to clutter the compiler with such stuff.

      edit: and in my opinion the beauty of go lies in the things that were left out intentionally :)

      1. 16

        in the go proverbs talk rob cites an example of a function that is basically duplicated verbatim between two packages. for a kit example, this is fine, except that then he goes on to explain that the tests reference both and check that they both work the same. this seems to defeat the purpose and is ultimately a less elegant solution that just having a package referenced by both.

        the phrase “copy a little code” is very, very disingenuous i find. working on large go repositories, if there is a bug or an issue in often copied code the refactors are painful messes that involve many find and replaces with regexes. code generation does not satisfy cases where the runtime itself would need to be changed.

        obviously there are extremes in stances on any topic, but “copy a little code” is so far to the other side of “don’t repeat yourself” that it’s hard to take seriously. there has to be a middle ground, and why (more widely available) generics in go keeps coming up.

        please keep in mind that slice and map are already basically generic types, along with append and copy as generic functions. it’s not the case that go is completely free of generics.

        1. 2

          “copy a little code” clearly has it’s disadvantages, but those should by now be clear for everyone thinking about using go. i think starting to push “random” features like this into the language does more harm than good, always risking to have more and more features requested.

          code generation does not satisfy cases where the runtime itself would need to be changed.

          what cases aren’t satisfied? you basically can write a whole compiler that generates go code, which should enable you to have any feature you want. that requires some work of course if you do complicated things, but just generating the same methods for different types is not really complicated to do with text/template for example. this way you wouldn’t need to regexp find and replace stuff.

          another option is to use interface{} and use type switches/type assertions. that would throw away type checking at compile time of course.

          1. 8

            that would throw away type checking at compile time of course.

            Among other things, this is what generics solve. I cringe anytime I have to use interface{} because I now have to be doubly, or triply, careful when playing the role of the type analyzer to ensure that I’m not doing something silly by accident that the real type analyzer (e.g. not my head) is blind to. Over time, this is harder to do accurately as code become more complex…

            (edit: typo in over time)

            1. 2

              …which should enable you to have any feature you want. that requires some work of course if you do complicated things, but just generating the same methods for different types is not really complicated to do with text/template for example.

              I am more puzzled by the philosophy behind this sort of thinking, than the thinking itself.

              1. 1

                I am more puzzled by the philosophy behind this sort of thinking, than the thinking itself.

                maybe i just have read too many old compsci books.

                apart from this: if one needs generics that hard, maybe just use another language? there are plenty to pick from ;)

                edit: i also think that code generation is different from cpp macro stuff as it is not happening opaquely at compile time but before. you can inspect the generated source easily.

                1. 3

                  edit: i also think that code generation is different from cpp macro stuff as it is not happening opaquely at compile time but before. you can inspect the generated source easily.

                  But how do we avoid this becoming something that is opaque and bespoke, handled on a per-project basis? C projects often do end up with a large library of macros which are more or less ad-hoc extensions C. If we allow for a moment that in static languages, generics are more or less code generation, then we can interpret the request for generics as a desire to standardize that layer of the toolchain. Maybe it doesn’t need to be part of the compiler but it would become more or less part of the environment, in the same way that pip is part of Python even though it’s not a part of python.

                  1. 1

                    generics are hard sure, but golang already has generics, they just aren’t user accessible.

            2. 2

              I’m not a huge fan of generic either. I’ve been perfectly happy in C without them, and consider generics to be a workaround for the type system more than an actual feature.

              1. 11

                People still build generics in C using the CPP. The GNU Scientific Library’s type system is one prominent example. In fact, templates in C++ were just trying to codify and standardise the pre-existing practice of CPP templates.

                1. 8

                  The generic red-black tree implementation hiding inside FreeBSD’s malloc is another famous/infamous example.

                  It appears there was a debate on adding something similar to the Linux kernel.

                  1. 2

                    Yeah, you can use macros to make crappy generics (and I have done that in the past), but it’s difficult enough that I don’t do it all the time, which keeps the code simpler. If templates are absolutely required to get any non-trivial task done, that suggests to me that the type system is far too strict. If more layers of code need to be generated you might as well switch to a higher level, dynamic language.

                    1. 1

                      …you might as well switch to a higher level, dynamic language.

                      Many applications where we see this need – the generic red-black tree in FreeBSD mentioned earlier is an example – are cases where type safety and fairly aggressive optimization are being used in tandem. Switching to Python wouldn’t help.

              2. 5

                The OP lists 4 proposals, the last of which is really detailed.

              3. 3

                If you want to play with generics and Go’s goroutines and channels, I combined the gccgo runtime with Nim: https://github.com/stefantalpalaru/golib-nim

                This is how Nim’s generics look like: http://nim-lang.org/docs/manual.html#generics

                The golib-nim implementation itself makes use of generally available generics to do what Go does only in the compiler: https://github.com/stefantalpalaru/golib-nim/blob/e01a45d5ae262a3f1596542112b8c825a3c52d50/src/golib.nim#L282