Hacker News new | past | comments | ask | show | jobs | submit login
The Generic Dilemma in Go (swtch.com)
36 points by fogus on Dec 3, 2009 | hide | past | favorite | 24 comments



I wish we could get back to using "Go" as a reference to the board game.


I agree. I got way too excited seeing multiple articles about Go in HN, but started wondering a moment later why there would be more than one such article about a board game, as wonderful as it is.


Way back when I played go with a few friends in college, we started calling it "baduk" (the Korean term) because the term "go" always took a second to register if you weren't already expecting it based on context. It's a really unfortunate word to try to borrow into English. To name a language "Go" when they knew most of their users would discuss it in English was just stupid.


I'd like to hear a compelling justification for generics in a language where you can add methods to any type, and every type implements an interface just by implementing all of the methods. I suspect that all of the reasons have to do with compile-time checks. (But in the domains where I do my work, it's fine to get by with runtime checking, so I admit I don't have complete in-depth knowledge on the subject.)

How about letting the programmer have it both ways? Let the programmer request either macro expansion or implicit boxing. The default would be implicit boxing, which would allow for fast compilation. The programmer could then specify macro expansion for certain specific types. This enables both rapid initial development and optimization and generation of compact runtime representations and fast code.


Having a vector or map collection where you can call methods etc. on elements without having to do a typecast, and know that the method call will work (i.e. is statically typed), is useful. It also stops you (or more likely, someone else on the team) from adding the wrong kind of thing to the collection.

If you don't understand the benefits of static typing, it's likely that you won't understand why generics can be preferable to polymorphism in containers.


If you don't understand the benefits of static typing, it's likely that you won't understand why generics can be preferable to polymorphism in containers.

Well, thanks. I do understand the benefits modulo refactoring. How about answering the question?

It also stops you (or more likely, someone else on the team) from adding the wrong kind of thing to the collection.

I just don't see this sort of thing. Maybe I've been lucky. But I've worked as a consultant for the vendor of a couple of Smalltalk implementations. I've been at many dozens of sites. I've worked as a programmer in 5 different development shops. I just don't see this happening a whole lot. If anything, I see unexpected things shoved into instance variables sometimes, but that's it, and it's just not that common.

It's not that I don't see the potential benefits of static typing. I just don't see the cost-benefit being that compelling.

Now, back to refactoring. I've often cursed not having the type annotations in the middle of a refactoring. But that's always been not knowing what's in some instance variable or temporary. With one exception, I've never cursed about not knowing what's in some collection -- and that had nothing to do with the collection! Maybe I've just been lucky and worked in shops where everyone knew heterogeneous collections aren't that great an idea?


> It's not that I don't see the potential benefits of static typing. I just don't see the cost-benefit being that compelling.

Now you are not talking about generics in Go, but a major philosophical position in programming language theory. I think your question is disingenuous. It is because you don't understand why some people prefer static typing that you don't understand the need for generics. Until you do understand that, you'll remain unenlightened with respect to generics.


Now you are not talking about generics in Go, but a major philosophical position in programming language theory. I think your question is disingenuous.

Specifically, I'm asking about people's actual experience. My question is sincere. I am not interested in people's preferences or their "philosophy". What is their experience? Also note that I allude above to having cursed the lack of types in Smalltalk at times. This doesn't seem so significant for collections.

I'm asking: Is putting the wrong thing into a collection really such a big deal? What is the actual experience? I gave mine. What's yours?

EDIT: Wow, it seems like just mentioning "static typing" should now be included in "Godwin's Law"! Rational discussion has become impossible!


Here you 'go': http://golang.org/src/pkg/sort/sort.go

http://golang.org/doc/go_spec.html#Type_assertions is possible, but it is costly. Basically, you either have to go through the tedium of writing "convenience" boiler plate (per above sort.go) or bite the runtime hit.


It's worth noting that "slow compilation" often translates directly into "slow programmers".


What's wrong with using both approaches: debug binaries get compiled with boxing generics, while release compiles using macros?


Scala offers both (not in a release version yet, but not far off) by way of @specialize. http://www.scala-lang.org/sid/9


Or have the former as the default, and allow the programmer to opt for the second, if the optimization is needed?


Cool idea. Has this been done in any language before?


It was my understanding that the Go language is still a moving target; the something closer to the final language spec should be known before discussing what it is missing.


This post is by Russ Cox, one of the designers of Go. He's asking for input into the design process.


Where does the Haskell type system fit into his description?


If you ever use GHC, you'll notice how slowly it compiles. However, this dilemma (trilemma?) is a false one. You can have unboxed (in relevant cases) generics in a language that compiles faster than C++ with full-blown templates. C# and Ada come to mind.


Ada in particular escapes this burden by requiring explicit generic instantiation, so at least you know how many of them you're dealing with.


In the most general case it uses boxing strategies, but it's also able to behave like C++ with certain compile-time optimizations turned on (at the cost of slowing down compilation). There's a lot of literature out there about how to take advantage of those optimizations. It's a fairly involved topic.


There are a whole host of ways that Haskell supports (or has been extended to support) generic programming. There's a big overview here:

http://www.haskell.org/haskellwiki/Research_papers/Generics

In the simplest case, generic programming in Haskell is done using type classes (similar to OO "interfaces"), often with the GHC extension for derivable type classes. If I understand correctly, this is generally implemented by implicitly passing a table of type information to the generic function at runtime, though I believe that compilers are able to optimize this away at compile time in some (most?) cases.

I'm not sure how well any of this would apply to Go, which doesn't have Haskell's type system.


No, the simplest case for Haskell would be type variables. For example, the map function doesn't need typeclasses at all:

map :: (a -> b) -> [a] -> [b]

For the record, in Go+generics, this might look something like:

func map<A,B>(f func (A) B, xs A[]) B[] { ... }


Good point, I forgot that even simpler cases in Haskell are generic too.


The rest of Cox's posts are also great reads.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: