16 ms·
After watching Rob Pike's Go Proverbs talk I am pretty convinced generics, as much as some would want it, will never happen. He proselytizes "just copy a little
by bigdubs 11y ago
After watching Rob Pike's Go Proverbs talk I am pretty convinced generics, as much as some would want it, will never happen. He proselytizes "just copy a little code here and there" quite clearly, which is at odds with the complexity that generics would add.
- ktamura 11y agoThis. For better and for worse, Go was designed for "simplicity", and generics are anything but simple. I'd be very, very surprised if Go thinks about generics in earnest anytime soon. I don't say this in anyway to eulogize Go: In some ways, Go is pathetically unexpressive. That said, it currently fills that gap for writing middleware between C sacrificing too much developer productivity and Perl/Python/Ruby/PHP sacrificing too much performance. Generics would be nice to have for this core use case for Go, but it's probably not critical.
- slantedview 11y agoGenerics can be (relatively) simple - see C#, they just tend not to be in many implementations.
- bigdubs 11y agoCLR (the C# runtime) generics are fully reified and about the most complicated and robust implementation available. It dynamically emits and loads types whenever a new generic parameter is seen for a function or type. This is very, very hard to get right and is not very performant. It also puts a lot of burden on the runtime vs. the compiler. Go expressly tries to keep the runtime as small as possible.
- pcwalton 11y agoCLR-style just-in-time monomorphization is plenty performant: in fact, it's just about ideal. It's also not that difficult when you have a JIT when compared to the complexity you need for speculative optimizations of hot spots anyway. In any case, the .NET approach isn't an option for AOT compilers like those of Go. For Go, the only reasonable option is ahead of time monomorphization, which really isn't that bad.
- pjmlp 11y ago.NET also has AOT compilation, which HNers seem to keep forgetting about.
- agentS 11y agoMonomorphization is not a reasonable option, in my opinion. It forces the compiler to accept some truly awful running times for pathological cases. Atleast quadratic, probably exponential. For languages that have reflection or pointer maps for GC or debug information for types, it can force large blowups in space as well. Go has all three of these. The implementation would likely require runtime code-generation (or accept warts like Rust's "object safety"). Indeed, all of Ian's proposed implementations are polymorphic and seem to avoid each of these issues at first glance. The only advantage of a monomorphic implementation is performance, and considering the downsides, this'd be premature optimization forced by a language spec. If its actually performance critical, I imagine it'd be easy to write a program that monomorphized a particular instantiation of the generic types. Indeed, the compiler would be free to do that itself, if it felt it would be worth it. Small, guaranteed non-pathological scenarios for instance. Where if you guarantee monomorphization in a language spec, the compiler and all users are forced to accept the downsides in all instances, in exchange for often meaningless performance gains (example: any program that does computation then IO).
- the_mitsuhiko 11y agoIf generics were not a studied and well implemented concept I would agree. But we live in a world where this is just not the case. I would take a slightly slower compiler with generics support any day over the mess that go devolves into because of the lack of it.
- pcwalton 11y agoIt's really not bad in practice. I've measured the amount of compilation time that generic instantiations take up and it's always been pretty low. Something like 20% (it's been a while, so take with a grain of salt), and that's with a naive implementation that doesn't try to optimize polymorphic code or perform ahead of time mergefunc. 20% is well within the project's demonstrated tolerance for compiler performance regressions from version to version. And you can do better with relatively simple optimizations. Generic compilation has been well-studied for decades; there are no unsolved problems here. I would heavily advise against trying to do better than monomorphization with intensional type analysis (i.e. doing size/alignment calculations at runtime). We tried that and it was a nightmare. It didn't even save on compilation time in practice because of high constant factor overhead, IIRC. Monomorphization is one of those things, like typechecking in ML, where the worst-case asymptotic time bounds look terrible on paper, but in practice it works out fine. People point to C++ compilation times as a negative counterexample, but most of the compilation time here is in the parsing and typechecking, which a strongly typed generics implementation will dodge.
- pcwalton 11y agoGenerics are a very simple feature as implemented in, for example, SML or OCaml. They're much simpler than Go interfaces, in fact.
- eru 11y agoGenerics become complicated when you have other subtype relationships, don't they? (That's why SML, OCaml and Haskell don't really do inheritance, isn't it?)
- Intermernet 11y agoGo doesn't do inheritance either. It has type embedding, but it's not the same. In the most recent of Ian Lance Taylor's proposals (Type parameters, 2013 [1]) he summarizes: > The implementation description is interesting but very complicated. Is any compiler really going to implement all that? It seems likely that any initial implementation would just use macro expansion, and unclear whether it would ever move beyond that. The result would be increased compile times and code bloat. So I'm pretty sure that the logic is acceptable, but it conflicts with Go's core goals of simplicity and compilation speed. [1]: https://github.com/golang/proposal/blob/master/design/15292/2013-12-type-params.md https://github.com/golang/proposal/blob/master/design/15292/...
- masklinn 11y ago> Go doesn't do inheritance either. It has type embedding, but it's not the same. It does have interfaces though.
- Intermernet 11y agoThis is generally brought up as the reason that Go doesn't need generics. I tend to agree with this. I've yet to come across a use-case where the current system is too difficult to deal with, but there are other people who have hit this limitation. Maybe this can be solved by simply modifying the parsing of the keyword "type" (Or adding a reserved type "T") and telling developers that the functionality of "go generate" will automatically (in the compiler) expand and create type methods at compile time, and build the type generation into the compile phase, rather than a manual pre-compilation phase. I haven't considered the problems with this approach, but I assume Ian et al have. It seems to me that the generated code approach could be spliced into the compiler with a few key-word parsing changes, but I'm not going to assume that the Go team haven't already thought of this, and there are probably problems with the idea that I haven't considered, above and beyond spec / compatibility promises etc.
- catfest 11y agoI don't see why you'd choose Go instead of a JVM language like Java, you get the language simplicity (plus features like Generics) and the performance upside too.
- riffraff 11y agoSingle small binaries are easy with go, very hard with java.
- incepted 11y ago> Single small binaries are easy with go With static linking? I don't think so.
- dikaiosune 11y agoCompared to a JAR with many dependencies and no option for LTO?
- pjmlp 11y agoJava 9 brings LTO via jlink.
- mappu 11y agoDoes golang have LTO? (maybe only in gccgo?)
- sievebrain 11y agoYou can make an executable "fat jar" with Capsule. It has a little shell script prepended to the JAR which means you can run it like "chmod +x foo.jar; ./foo.jar" You can do dead code elimination and other forms of LTO using ProGuard. Just watch out for code that uses reflection. Java 9 will include a less aggressive version of the same thing which performs various link time optimisations like deleting modules (rather than individual methods/fields), statically pre-computing various tables, and converting from JAR into a more optimised (but platform specific) format. That tool can also bundle a JRE in with your app, giving you an "tar xzvf and run" deployment model. It's not a single file, but it makes little difference in practice. The same tool can build DEBs, RPMs, Mac DMGs and Windows EXE/MSI installers with a bundled and stripped JRE too.
- boulos 11y ago> I'd be very, very surprised if Go thinks about generics in earnest anytime soon. I might agree if the submitter wasn't a person on the Go team trying to highlight some recent thinking ;)
- sievebrain 11y agoI thought that too, but then at the end he says he has written such articles many times before over a period of years, and nothing ever came of them.
- bad_user 11y agoI think Go people have a very strange definition for simplicity, much like the population at large actually, but that's a shame really. Simple means composed of a single element, not compound, unentangled, being the opposite of "complex", which of course means consisting of many different and connected parts. Instead Go people prefer the term to mean the now more popular meaning, which is "easy to understand, familiar". I think a parallel can be drawn with another word from the English language: "free". You see, English doesn't have a word for the latin "liber" (libre, at liberty), like other romance languages have and I can name at least Italian, Spanish, French and Romanian (my own tongue). In these romance languages there's a firm distinction between libre and gratis, whereas in English there's no adjective signifying liberty without also meaning "at no monetary cost". I find that to be interesting and I bet it happened most probably because at some point in time these 2 issues were correlated. Back to simplicity, while you can often correlate simplicity with easiness, mixing the terms is unjust because sometimes simple things aren't easy at all and sometimes easy things aren't simple at all (much like how sometimes gratis things are restricted and liberties aren't gratis). Speaking of which in my own native tongue the word for "easy" is also used to signify weightlessness (light, soft). Makes sense in a way, but you can see how language works. And it would be a shame to lose the true meaning of "simple", just because its usage is at hand when trying to describe things that are or are not desirable. As in the end, this is how the meaning of words gets diluted and lost: because of our constant desire to make other people believe our ideas and buy our shit. So we exaggerate. Just a little, after all, we are only going to end up with a language that's ambiguous. What does it matter if "open source" has had a clear definition since OSI and that it wasn't in use before that, it's marketable dammit, so lets use it for all shit that has source-code available. Etc, etc. And I get it, saying that generics aren't easy isn't so appealing, because that would be an acknowledgement of one's own capabilities and knowledge, being a metric relative to the one who's speaking. Whereas simple is an objective metric, with things being simple or complex irregardless of the person that's passing judgement. Still, generics are only as complex as static type systems. When you have a statically typed language, generics are a natural consequence. And if you don't add generics, then you need to add an "Object", "Any", "dynamic" or whatever you want to call it, which would be a whole in that static type system, not to mention introducing special cases (like the builtin arrays and maps) and that's complex by definition. Java did as well, introducing generics at version 5, when it was too late to do it cleanly and the result isn't nice at all ;-)
- slantedview 11y agoIt's also at odds with hard-learned lessons of the rest of the software industry, like don't repeat yourself. Golang is doomed to relearn these lessons.
- codehusker 11y agoWe also have the hard-earned lessons of taking DRY to its extreme (left-pad). Where you draw the "copy a little code" line is subjective.
- danellis 11y agoExactly what lesson do you think was learned? Do you think that languages that have had left-padding functionality in their standard library since forever (and there are lots of them) are going to remove it now? There was definitely a lesson to be learned there, but it wasn't the one you're implying.
- Ericson2314 11y agoYay sanity! All the anti-code reuses have taken the opportunity to come out of hiding, but they're no less wrong. The aggressive code reuse in the node ecosystem is, and remains, the quality of it I respect the most.
- danieldk 11y agoFirst of all, generics is hardly DRY to its extreme. I think that everyone agrees that copying e.g. a balancing red-black tree implementation just to specialize it for another value type is a pretty bad idea. So then you either end up with some kind of runtime polymorphism or parametric polymorphism. Some Go users argue that runtime polymorphism is enough, but you often run into cases where you have a func frobber(s []SomeInterface) ... However, you end up having a []ConcreteType where ConcreteType implements SomeInterface. However, you cannot simply pass a []ConcreteType to frobber because the memory representation is different and you have to construct a new slice with the interface type, etc. Also, I don't think left-pad is an example of extreme DRY (though it should be part of a standard library). It's not an example of extreme DRY, because I think a substantial amount of programmers wil implement it incorrectly. As long as many Java-wielding friends still believe that a single char can represent any unicode code point, I have no reason to believe that the average monolingual English-speaking Go programmer will realize that you can't simply do something like: padLen := targetLen - len(str) (BTW, Go's fmt package provides padding.)
- reycharles 11y agoRob Pike's repository 'filter'[0] contains implementations of map ("Apply"), filter ("Choose", I believe), and fold/reduce ("Reduce"). The code is an ugly mess, and the implementation shows that he probably hasn't used any of these standard functions in other languages (see the weird permutations of 'filter' in apply.go, or my patch for his fold/reduce implementation[1]). The README is also quite arrogant, IMO. > I wanted to see how hard it was to implement this sort of thing in Go, with as nice an API as I could manage. It wasn't hard. > Having written it a couple of years ago, I haven't had occasion to use it once. Instead, I just use "for" loops. > You shouldn't use it either. [0]: https://github.com/robpike/filter/ https://github.com/robpike/filter/ [1]: https://github.com/robpike/filter/pull/1 https://github.com/robpike/filter/pull/1
- tazjin 11y agoThis is what people mean when they say that Go has disregarded everything we learned in the programming language community in the last decades. Sure, some people are productive in it and that's fine - but for those of us who have worked in better languages taking the step down is unattractive.
- thegenius2000 11y agoI'll grant that Go is lacking in generics, but IMHO, the opposite is true. Go is thriving because although not perfect, it is one of the few languages which seems to have learned lessons from the failings of C++, Java; and from the successes of the more dynamic/scripting languages (team Python, Ruby etc.). Go isn't a step down, it's a step backwards from the edge of the cliff.
- aninhumer 11y agoThe lesson Go seems to have learned is that, since C++ and Java burned their fingers, clearly fire is too dangerous for humans. The thing that makes it painfully obvious to me that Rob Pike hasn't bothered to learn anything from the PL community is that Go has nil. That just shouldn't happen in a modern language.
- jhoechtl 11y agoGiven the Autor is Ian Lance Taylor I personally do not think that there is no chance for implementation
- trhway 11y agomental exercise - replace C++ with "generics" and git/kernel/etc with "Go" here http://harmful.cat-v.org/software/c++/linus http://harmful.cat-v.org/software/c++/linus
- jcoffland 11y agoLinus is clearly throwing his weight around here. If anyone else were to act this way and use such language we would all call him or her an asshole. Besides his main point is that C++ is not great for low level code. I don't see how this applies here.
- trhway 11y agowe see things differently. In my view Linus is speaking free here. Many others refrain from speaking free and truthfully for fear of being called an asshole. I see different main point. In my view Linus narrows the domain of his speech to system-level (not low-level!) code just out of basic intellectual honesty which implies to speak with authority only where your experience and knowledge are.
- jcoffland 11y agoWhen he says, "YOU are full of bullshit," is that the intellectual honesty part? Some people are merely assholes constrained by social pressure other people are actually being honest when they are nice. It's hard to believe this when you are one of the former. I agree with your system-level vs. low-level point except that he also talks about git which is neither.
- trhway 11y ago>When he says, "YOU are full of bullshit," is that the intellectual honesty part? if the guy is full of it then not saying it would be intellectual dis-honesty :). You and me belong to the different mindsets separated by a Grand Canyon. Man, i understand the reasons behind PC-culture, yet i just don't agree with the required trade-off. It is pretty much the same as security vs. privacy & other freedoms - there is really no meaningful debate possible beside clearly stating your own position as these mindsets are separated by the same size canyon. It is not separation of reasoning, it is separation of the choice of the top priority - in most cases that choice is deeply unconscious, and i have my personal theory connecting it to evolution and natural selection :) It is not that people on different sides don't understand the reasons of the other side, it is just people on each side are separated by their choice of the reasoning they assign higher priority to, like me and you in this case.