3 ms·
As a type theorist and programming language developer, I’ll admit that’s a fairly reasonable design for generics. I’m still a bit disappointed by the restricti
by evincarofautumn 8y ago
As a type theorist and programming language developer, I’ll admit that’s a fairly reasonable design for generics.
I’m still a bit disappointed by the restrictions: “contracts” (structural typeclasses?) are specified in a strange “declaration follows use” style when they could be declared much like interfaces; there’s no “higher-level abstraction”—specifically, higher-kinded polymorphism (for more code reuse) and higher-rank quantification (for more information hiding and safer APIs); and methods can’t take type parameters, which I’d need to think about, but I’m fairly certain implies that you can’t even safely encode higher-rank and existential quantification, which you can in various other OOP languages like C#.
Some of these restrictions can be lifted in the future, but my intuition is that some features are going to be harder to add later than considering them up front. I am happy that they’re not including variance now, but I feel like it’ll be much-requested and then complicate the whole system for little benefit when it’s finally added.
- kyrra 8y agoThey are truly looking for feedback on these proposals. If you have thoughts on how could change to be potentially more compatible for future additions, consider doing a blog post write up and submitting it to them.
- ianlancetaylor 8y agoThanks for the comments. We tried for some time to declare contracts like interfaces, but there are a lot of operations in Go that can not be expressed in interfaces, such as operators, use in the range statement, etc. It didn't seem that we could omit those, so we tried to design interface-like approaches for how to describe them. The complexity steadily increased, so we bailed out to what we have now. We don't know whether this is is OK. We'll need more experience working with it. I'm not sure that Go is a language in which higher-level abstraction is appropriate. After all, one of the goals of the language is simplicity, even if it means in some cases having to write more code. There are people right here in this discussion arguing that contracts adds too much complexity; higher order polymorphism would face even more push back.
- evincarofautumn 8y agoYeah, I’m not sure higher-level abstraction is right for Go either—like I said, I do think the tradeoffs in the generics design are ultimately reasonable, given the design constraints. I guess it’s those very constraints that get to me. This is going to sound harsh, but I believe the goal of “simplicity” is already very nearly a lost cause for Go. The language is large and lacks any underlying core theory, with many features baked in or special-cased in the name of simplicity that would have been obviated by using more general constructs in the first place; the language is not simple, it’s easy for a certain subset of programmers. Adding convenience features here and there and punting on anything that seems complex by making it an intrinsic has led to a situation where it’s increasingly difficult to add new features, leading to more ad-hoc solutions that are Go-specific. This leads to the same problem as languages like C++: by using Go, developers must memorise details that are not transferable to other languages—it’s artificial complexity. A major source of this complexity is inconsistency. There are few rules, but many exceptions—when the opposite is more desirable. There are tuple assignments but no tuples. There are generic types but no generics (yet). There are protocols for allocation, length, capacity, copying, iteration, and operators for built-in containers, but no way to implement them for user-defined types—the very problem you describe with contracts. Adding a package dependency is dead-easy, but managing third-party dependency versions is ignored. Error handling is repetitive and error-prone, which could be solved with sum types and tools for abstracting over them, but the draft design for error handling just adds yet another syntactic special case (check/handle) without solving the semantic problem. Failing to reserve space in the grammar and semantics for features like generics up-front leads to further proliferation of special cases. Virtually all of the design decisions are very conservative—there’s relatively little about the language that wasn’t available in programming language research 40 years ago. I don’t mind writing a bit of extra code when in exchange I get more of something like performance or safety wrt memory, types, race conditions, side effects, and so on. But Go’s lack of expressiveness, on the whole, means it doesn’t provide commensurate value for greater volume of code. But it could! None of these issues is insurmountable, and the quality of the implementation and toolchain is an excellent starting point for a great language. That’s why I care about it and want to see it grow—it has the immense opportunity to help usher in a new era of programming by bringing new(er) ideas to the mainstream.