5 ms·
Purely out of curiosity, do you know of any talk that would explain in detail why things like swift's protocol extension can be implemented in conjunction with
by bsaul 11y ago
Purely out of curiosity, do you know of any talk that would explain in detail why things like swift's protocol extension can be implemented in conjunction with generics, and go interfaces can't ?
From the outside, the two features (swift's protocol with extensions and go interfaces) seem a bit close, so that made me wonder. I didn't have the time to think too much in detail about it, so i'm just wondering if anybody already had.
- pcwalton 11y agoYou certainly can implement Go-like interfaces alongside generics. There's nothing inconsistent about them.
- arihant 11y agoYes, but the typical consequences that arise out of that do not fit with design goals of Go. Just off the top of my head - boxed types, for example lead to Java-style inheritance patterns. This sits awfully with composability and readability of Go code. You read Go code like a tree. You read Java code as multiply linked list.
- crawshaw 11y agoIt can be done, the question is can it be done in a way that fits with everything else in Go? There are technical drawbacks in the implementation of parametric polymorphism that don't suit Go's design goals: http://research.swtch.com/generic http://research.swtch.com/generic.
- coldtea 11y agoAll of the supposed reasons given in that post have been answered to death by multiple people (including PL experts), and none holds to much scrutiny. "We just can't be bothered" or "we don't think they're much good, and we don't have a need for them" would be a much more realistic answer.
- crawshaw 11y agoI haven't seen any rejoinders to that document that contradict the fact that you pay for parametric polymorphism with either slower compilation or slower runtime. Go isn't interested in either being slow. Any generics solution has to have fast runtime, because they need to replace the builtin parametric slices and maps. And the compiler is already too slow, in fact there's a lot of work slated to try and make it faster. Lots of effort went into studying the problem, so it most definitely isn't an issue of "can't be bothered".
- pcwalton 11y ago> I haven't seen any rejoinders to that document that contradict the fact that you pay for parametric polymorphism with either slower compilation or slower runtime. I think the error in that reasoning is attributing this issue to generics specifically when this is actually a problem with code reuse in general. Say I have a linked list and want to use it to hold both integers or strings. My two options, in any language—whether that language has generics or not—are: (1) write specialized code for every type I want to use it with (go generate), potentially bloating the code and resulting in extra compilation time; (2) use some sort of existential type (interface{} in Go) and share the code but pay a performance cost at runtime. The dilemma arises because of the problem itself, not because of generics. It is of course right that there is a tradeoff here (although there are many other potential solutions that aren't at one extreme or the other, .NET-style JIT compilation or intensional type analysis for example). But not having generics doesn't eliminate the tradeoff. Generics are just a way for the compiler to automate the work that a programmer would otherwise have to do. If you don't have generics, you still have that dilemma, except that you have to write the code yourself instead of the compiler doing it for you.
- sirseal 11y agoThis is a fantastic explanation. Thank you for phrasing it so concisely.
- crawshaw 11y agoThat is a powerful theoretical concern that I shared when I first experimented with Go several years ago. In practice I have not found it to not be a problem. It seems (and this is purely an analysis of my own experience and the large amount of Go I read inside Google) that the types of data structures and algorithms I need parametrized follow a power law distribution. Mostly I need a list, or a hash map, and the builtin slice and map types almost always meet my needs. For the long tail of parameterized types in that power distribution, it appears that either it is not a performance hot spot, in which case I can borrow from the dynamic dispatch tools in the language (that is, some variant of an interface{}), or performance is so critical that even in C++ there is no obvious generic data type. The latter is an interesting case I ran into in my prior life as a C++ programmer, and in OCaml. Someone had created a generic version of a data structure (usually more than one someone), but what I needed in my performance hot spot was some variant that wasn't captured by the parameterization. An old example that comes to mind: I inherited a struct whose memory layout described a wire protocol. It had an 8-byte piece of padding in the middle of it. That was the perfect place to hide the pointer for a linked list I wanted to create in an intermediate step. Of course, none of the many template-based linked list data structures I had in C++ could do that, so I rolled my own. So as unexpected as this may be, I find a combination of map/slice, interface{}, and rolling my own meets my generics needs in Go well enough that I wouldn't want to trade off slower compilation for it, or bad compile-time error messages. I still miss generics, and it may be that the particular kinds of programming I do mean I miss them less than others. A co-worker with nearly as much Go experience as I have says he misses them more often. The ones that come up most often for me are sorting and some kind of ordered map, but even those bug me less than once a month.