> [...] but because its authors and community is incapable of admitting problems when they see them.
What evidence did you see to make this conclusion? I can only find from their FAQ[0]:
"Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.
Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it. Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.
That answer has been there for a while. There hasn't really been any indication that the issue actually is open, other than a refusal to state outright "no generics in Go".
I can't decide if my biggest problem with that answer is that it suggests that the primary use case for generics is generic containers (when, really, the main benefit of generic containers is being able to implement generic algorithms on said containers, like pmap), or whether it's the suggestion that breaking type safety in a statically typed language is a feature.
interface{} is barely an improvement over void*. The need for it suggests an insufficiently powerful type system. Go should either have a type system powerful enough not to need an explicit convention to avoid it, or it should have been dynamically typed.
I believe that this is evidence enough that they're downplaying the importance of generics.
Specifically, the claim that "maps and slices" can replace the ability to write abstractions such as futures, promises, observables as well as generic function such as map, reduce etc comes off as either naive or disingenuous
Furthermore, the "cost" of these features seems overstated to me. A lot of languages and runtimes already implement generics without significant compile-time or run-time overhead - why is it that hard for Go to do that?
I don't have the hard numbers to back up the cost question, but I believe one contributing factor to the claims appearing "naive/disingenuous" to you may stem from the fact that you may be looking at the language Go from a totally different perspective than the creators when they first envisioned the language (I could be very wrong in this regard):
"Go was designed to address the problems faced in software development at Google, which led to a language that is not a breakthrough research language but is nonetheless an excellent tool for engineering large software projects"[0]
They go on to list some concrete points on the type of problems they are trying to solve:
- slow builds
- uncontrolled dependencies
- each programmer using a different subset of the language
- poor program understanding (code hard to read, poorly documented, and so on)
- duplication of effort
- cost of updates
- version skew
- difficulty of writing automatic tools
- cross-language builds
So while I can see generics helping their goal of, say "duplication of effort", I can also see it negatively impacting bullets "different subsets of the language" and maybe "poor programming understanding" since debugging generics can be extra-painful.
I might not agree with the way they value generics but to me, it does seem reasonable given their design vision and goals.
With the right implementation debugging generics wont be hard. It doesn't have to be C++'s version of generics.
And I'm not buying the poor programmer understanding argument. Generics aren't that complex, they're just parameterized types. The fact that basic language libraries such as maps and slices cannot be implemented without them speak volumes about how fundamental they are when building abstractions.
My point is that most of the backpressure against generics seems to stem from perceived added complexity to the compiler and type system, and thats all. But I'm not convinced thats a valid argument. Truth be told, I'm not a language implementer. But I know that fast compilers and runtimes that implement generics exist, so I don't find the whole discussion believable.
> But I know that fast compilers and runtimes that implement generics exist, so I don't find the whole discussion believable.
Are you arguing that an implementation of generics in a programming language is free? (Whether it be performance or implementation complexity.) Because if not, then you admit there are trade offs. If there are trade offs, then it is conceivable that some circumstances (including programmer tastes) may lead to a valuation that is different from yours.
"Performance" of the compiler is a critical goal of the Go project. Could you point out for me an industrial strength compiler that supports a type system of your liking that can match the compilation speed of the Go compiler? (I can't think of one.) Because if not, then I'll have to invoke this: talk is cheap, show me the code.
> Are you arguing that an implementation of generics in a programming language is free? (Whether it be performance or implementation complexity.)
I am.
Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code.
Implementation complexity: You could add some constraints to generics, for example only interface types can be used as generic parameters, and all uses of variables/methods/functions with generic types need to have generic parameters given. In that case, there's no complexity for code that doesn't use generics. Also, generics could actually be implemented as a preprocessor that would simply insert appropriate casts from/to interface{} at calls to generic methods. Since all variables/functions in Go are declared and have known types, you could of course go further and eliminate most generic parameter annotations.
> Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code.
That is incorrect. Using `interface{}` incurs a significant performance penalty at runtime because you end up boxing everything. For example, you cannot cast a `[]interface{}` to an arbitrary `[]A`.
In other words, no, `interface{}` is not `void*`, sorry. If it was, Go would not be memory safe. (See golang.org for their definition of memory safety. It is strictly superior to a language like C, but e.g., less than a language like Rust.)
Yes, but the tradeoff Go takes right now is "slow programmers," or "no generics." You are trading that in for "slow programs." This directly implies that generics have some sort of cost structure and are not free.
`interface{}` is very rarely used for writing "generic" code precisely because of its lack of type safety and performance implications. If you came up with a way to make it type safe without addressing performance, you've just implemented a generics scheme that will cause programs to be slower than they would be without generics (because people would start using them!).
I think it should be clear to every programmer that there are different trade-offs to be made when designing systems, including the trade-off between generic-code&fast-development&slow-speed and specific-code&slow-development&fast-speed. People that don't get that shouldn't be programmers, and people that get it should have the freedom to make their own trade-offs.
In other words, the only "cost" of generics, thus, is the social cost (there is no purely technical cost). Here, it boils down to the philosophical/political freedom-vs-safety question, and I strongly incline towards freedom. Go does not. Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.
> Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.
I just got through telling you that this type of use is actively discouraged, so no, people aren't using it as often as you might think.
If you want generics, you've got to pay for it. The implementation you've suggested requires a runtime performance penalty to use generics. Therefore, you have not demonstrated that generics are free.
Is there any evidence for this claim? After a quick Google session, the best I could find was a forum thread 4 years ago claiming that `dmd` was faster than `gc`. Is that still true today?
I think a lot of the complexity even in your examples of passing functions for generic actions like map/reduce is dealing with closures and scope. I don't know enough about golang to comment on its' internals, but as I recall there was a lot of work and effort that had to go into the .Net runtime and compilers in order to support lambdas and generics properly. Which, imho was more than well worth it.
There are likely other issues that golang needs to solve that are much higher priority issues, and there are flexible, even scripted languages that can handle higher level logic problems and scale very well. I wouldn't really expect to have to use generics for most of the problems I would look to go as a first language for a given problem.
Of course all of the above said, I'm a node.js fan and really like what it has to offer. It just depends on your use cases. Go is a really clean language/platform with a lot in the box, that I do appreciate. I would be surprised if they didn't support generics for v2, if not before. But I can see why they would want to punt the issue while there are bigger problems and needs to address.
What evidence did you see to make this conclusion? I can only find from their FAQ[0]:
"Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.
Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it. Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.
This remains an open issue."
[0] http://golang.org/doc/faq#generics