12 ms·
Idiomatic Generics in Go
- BruceIV 12y agoWhat happens if you want two different types of set? As-imports? (I've looked at Go, but not written in it.)
- bouk 12y agoYou can alias imports! http://learntogoogleit.com/post/63748050636/aliasing-imports-in-golang http://learntogoogleit.com/post/63748050636/aliasing-imports...
- wffurr 12y agoBut then I'm right back to having types named "IntSet" and "StringSet". Though at least they're not using copy/paste code implementations.
- NateDad 12y agoWell, they are using copy and paste, it's just automated. But is Set<int> really better than IntSet? Don't they carry the same information?
- metafex 12y agoI honestly have mixed feelings about this. It is a really nice showcase of what the standard library can do (walking the AST and modifying it) with little amount of code. OTOH it would be better to not make this a web-service. As much as it may seem to be convenient, integrating it with "go generate" (when it's ready) would probably be easier to use and not pose any security risks ;)
- jerf 12y agoSince go generate isn't out yet and the web service can work now, it's a good prototype of what can be done. Obviously once go generate is official anybody could do something like this themselves, even if this particular implementation is never ported.
- bouk 12y agoI agree the web-service is a terrible idea, I just wanted to see if I could implement it. It's also super insecure, as go fetches the package over HTTP (which you can see when you do go get -x gonerics.io/d/graph/string.git)
- barrkel 12y agoActually, I think the web service is the only interesting part of the idea. Generics via string substitution are as old as the hills, I remember doing the same thing for Pascal 20 years ago. (The factual accuracy of the statement that it was 20 years ago disturbs me. I'm getting old!)
- crazychrome 12y ago100% agree. it's a break through not because of the problem it's trying to solve, but the approach.
- zerr 12y agoI found a better solution - abandoned the language.
- swartkrans 12y agoWhat do you use instead now?
- lorddoig 12y agoCGI...shell script...
- bouk 12y ago:)
- eximius 12y agoanyone tested it yet? I mean, you can't put an unpatched shell scripted site in HN right after a new CVE and TELL us its a shell script... right???
- bouk 12y agoOf course I patched it, and I'm not using bash in the first place https://github.com/bouk/gonerics/blob/master/cgi.sh https://github.com/bouk/gonerics/blob/master/cgi.sh
- jerf 12y agoIt is worth pointing out that if the Go community settles on something like this as the solution, it negates one of the underlying arguments that the Go designers have against generics in the language. They have a set of criteria necessary for them before they are willing to put a solution in the language [1], and one of them is that they aren't willing to do C++-style template-based generics that involve compiling separate functions for every generic instance, causing the binary to grow in size. But all the other solutions that are headed into that gap are just one level or another of convenience wrapper around exactly that. If the Go community just starts doing this at scale, then there's really no reason not to pull that up and make it official. [1]: Whether or not you believe that they're just against them full stop and can't be budged no matter what, there's at least some claimed reasons.
- chimeracoder 12y agoFor context: Go has been my primary language both at work and for personal use for over two years now. > It is worth pointing out that if the Go community settles on something like this as the solution, it negates one of the underlying arguments that the Go designers have against generics in the language. It wouldn't really negate the underlying arguments; it would just mean that the community had grown and attracted developers who may not necessarily share that part of the language creators' original vision of the language. > But all the other solutions that are headed into that gap are just one level or another of convenience wrapper around exactly that. Well, focusing on "the other solutions" misses two things: First, many (I dare say most) Go developers[0] don't really use any "solution" for this other than the features built into the language itself. In other words, they're not out there writing alternative solutions because they genuinely don't perceive a lack of generics to be as big of a problem as other things, which they do write tools for. Secondly, there is a way to use interface{} to accomplish some (not all) of the same things that generics do, while still preserving type safety. Look at the functions in this Twitter client library I wrote: https://github.com/ChimeraCoder/anaconda/blob/master/users.go https://github.com/ChimeraCoder/anaconda/blob/master/users.g... All the endpoints use the same apiGet() function ("generic"), but they all return concrete types, and they are all typesafe - you will never get a runtime panic from any of those functions. This is more than Java's generics guarantee, due to the quirks of the way type erasure works there[1]. No, this isn't "generics", but it provides an alternative way of solving the problem most of the time (in practice), and isn't that what matters? And yes, this is not quite as clean as some languages which focus on having a very expressive and precise type system (ML, Haskell, etc.), but it provides enough type safety for me without requiring me to think consciously about the types that I am using (which I have to do when writing ML or Scala). [0] I mean people who write primarily Go at least 4-5 days a week, for work, as opposed to people who dabble with it for side projects but primarily use other languages. [1] TL;DR: Java's generics are converted to "Object" after compilation, which means that you can actually end up with runtime type errors that are detectable at compiletime, due to inheritance. (It's been a while since I used Java, so I won't provide an example, but they're easy to find online).
- crazychrome 12y agoHow about my own types?
- bouk 12y agoYou can use them like this: gonerics.io/d/set/github.com/crazychrome/package.git.Type The things it supports can be found in the tests https://github.com/bouk/gonerics/blob/master/template_params_test.go#L51 https://github.com/bouk/gonerics/blob/master/template_params...
- crazychrome 12y agoAwesome! Although I'm not a believer in generic but I think it's a bfd in the programming field which will be as important as the REST thesis, or ror. How about a service with similar approach that offers Parse to appengine migration: user calls a rest point like: generics.io/parse/github.com/crazychrome/package/user to configure fields and types requirements, then the service generate a repo contains codes can be deployed to appengine and 100% compatible with what Parse offers.
- liveoneggs 12y agobeing "idiomatic" is now the most important thing in Go, apparently.
- norswap 12y agoIdiomatic thinking in an idiotic language. (I don't really think Go is idiotic, although I do think it is lacking -- even when you consider its aim to be minimal.)
- theflubba 12y agoThrowing type-safety out the window is so 2006. Just use Scala.
- Animats 12y agoGo, which claims not to have either generics or objects, has both for built-in types. Channels and maps are both opaque objects and parameterized types. The argument that generics are unnecessary would be more convincing if those built-in types were not needed. The problem is adding generics without making a mess of things. This is harder than it looks. In the example, there's a set of "int", and a set of "string". A new set is created with set := set.New() in both cases. It looks like you could not instantiate "set" for both types in the same program without a name clash. That's no good. Parameterized types for Go make sense, but the types need to be given a user defined name each time you create one. With "generics as a service", you'd have to encode that name into the "import" statement, which is getting a bit clunky. Go's lack of generics is a reaction to the mess C++ made of them. In C++ the generics system turned into an entire compile time programming environment based on term rewriting rules. Nobody wants to go there again. But Go went too far.
- burntsushi 12y ago> Go, which claims not to have either generics or objects, has both for built-in types. Who is claiming that? > The argument that generics are unnecessary would be more convincing if those built-in types were not needed. This is a straw man that you're tearing down. The Go devs have always acknowledged the utility of generics. They just have a different set of trade offs that they are targeting. More to the point, there's absolutely nothing inconsistent with the position, "If we can make writing code easier with a little blessed generics without sacrificing our project goals, then let's do it!"
- discreteevent 12y agoIf a language is not dynamically typed then it's cumbersome not to have generics, that's for sure. On the other hand what I really like about go is that they are the only popular recent language that pushes back against a lot of modern features and says: "It doesn't matter how clever those features are, overall simplicity and consistency matters more." The point is that we really need this experiment. It's in everybody's interest that the go people push back and continue to keep the language minimal. In a few years time someone will say on the internet that unless you have features x, y, and z in a language you simply cannot be productive/concise/maintainable/performant/safe/not-a-blub. At that point it may be possible to point at some evidence and say "Well I noticed that those machine learning guys at myAppsTheGreatest.com wrote a large system in go". Then you can go study it and see if they really needed those features. You can also ask the developers who used it and hopefully some of them will also have experience in [insert crystalline functional language here] so you can get them to weigh up the pros and cons. Go is an experiment that is needed.
- bad_user 12y agoI personally like to think of simplicity as the opposite of entangled / intertwined, which is often at odds with easiness / familiarity. Rich Hickey has a very good presentation about it. I like doing that because then simple and easy are expressing 2 different things, both desirable but kind of orthogonal. > overall simplicity and consistency matters more Go took some good steps towards simplicity. OOP as present in languages such as Java is overrated and a primary reason for the complexity created. We could use some variations for this need for ad-hoc polymorphism that we have. Unfortunately Go doesn't go far enough by not addressing the need for type-classes or something similar. And the language doesn't have to end up with a type-system as sophisticated as Haskell if you want type-classes. Clojure has a similar mechanism called protocols and yet it doesn't have OOP in the traditional sense, Scala has implicit parameters solved at compile time that can be used to model type-classes and overall type-classes are a simplification because they cleanly separate data from behavior. Go also provides those channels as a more useful abstraction than plain threads. That's cool and all, but channels are not enough and a language should allow other people to evolve the language with even more abstractions for dealing with concurrency and parallelism, because there's no silver bullet. On top of the JVM people have built frameworks and libraries for actors, agents, csp, futures/promises, parallel collections, light-weight threads, STM, reactive programming / streams and most other things you can think of and the best a language can do is to allow evolution. One should not confuse a small set of features with simplicity. Java was also a language that refused in the beginning to have generics and then in version 5 it got an abomination - as in generics that don't specialize for primitives and that solve co/contra-variance by means of use-site variance and freaking wildcards, instead of the much saner declaration-site variance. This happened because backwards compatibility is important and an established language needs to be evolved by providing a sane migration path. Go is slowly losing its window in which it can make bold changes. Going back to your original point, a small set of features is bad if users cannot efficiently extend the language because the needed features aren't included. Having a small set of features is great, but it matters what those features are. I invite you to watch Guy Steele's "Growing a Language" presentation on this point, it's an astonishingly good presentation: https://www.youtube.com/watch?v=_ahvzDzKdB0 https://www.youtube.com/watch?v=_ahvzDzKdB0
- timtadh 12y agoI also miss generics in Go. It is especially a pain to implement a nice high performance collections library without them. I have been working on and off on a data-structures library and you have to go through a lot of hoops to make it nicely usable and your still end up with `interface{}` everywhere.[1] It should be noted that this is not the first attempt by any means. droundy implemented basically this several years ago.[2] The problem is these things are non-standard and I don't feel comfortable using them. I want generics but I want them as part of the language not as some weird third party CGI script. I also want them integrated into the template system. That way I can create type variables which must implement an interface. However, when the code is actually run, it isn't an interface object it is the actual object. Features like that would make them fit much better with the rest of the language. [1] https://github.com/timtadh/data-structures https://github.com/timtadh/data-structures [2] https://github.com/droundy/gotgo https://github.com/droundy/gotgo
- barrkel 12y agoThe key innovation here is that it uses the URL to do the parameterization. That's not what is implemented in your reference [2]. I think this approach is actually quite clever. It's clever because URLs belong to a global namespace. If you have third-party code that is also using an instantiated generic, your code should be compatible with it because you'll be using the same URL. Whereas locally-generated templates are more problematic - compatibility depends on build scripts etc.
- timtadh 12y agoI agree this does solve the `go get` problem. However, a better thing would be to improve `go get` and make it use an actual build system. `go generate` is a step in the right direction but they expect you to check the generated sources in. I would prefer a tool chain that allowed your API customers to do code generation from your library. However, these things are more complicated and the Go Author's are probably right to do the simplest thing first.
- wyager 12y agoGo seems to be re-inventing C++ and Java one step at a time. Go didn't learn from history, and is doomed to repeat it.
- zwieback 12y agoThat was my thought, unless the Go guys send a signal what they will add in the future. Otherwise you'll have tons of competing solutions and a lot of anger when a winner is chosen a year or two from now. With C++ you have boost as a funnel, C# has MS giving previews of what they will add, similar for Java. If Go chooses to stay purist their world will fragment.
- alkonaut 12y agoIf workarounds like these are common in the use of Go then leaving it out of the language was a mistake. The argument that generics comes at a complexity cost is nonsense: unless used it has no cost, the code would look like code does today. The complexity added by NOT having generics in a strictly typed language is enormous (as these examples show).
- bkeroack 12y agoWhenever this issue comes up (and on HN, it never appears to die), I'm reminded of an eye-opening moment I had reading Rob Pike's excellent essay "Less is Exponentially More" (http://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html http://commandcenter.blogspot.com/2012/06/less-is-exponentia...). An excerpt (original emphasis): "Early in the rollout of Go I was told by someone that he could not imagine working in a language without generic types. As I have reported elsewhere, I found that an odd remark...What it says is that he finds writing containers like lists of ints and maps of strings an unbearable burden. I find that an odd claim. I spend very little of my programming time struggling with those issues, even in languages without generic types...But more important, what it says is that types are the way to lift that burden. Types. Not polymorphic functions or language primitives or helpers of other kinds, but types." It seems to me that people program heavily with types because that's what compilers are really good at. Therefore that's what most languages give us. But I don't want to be constructing huge, complex type hierarchies with every application. If I'm spending more time on that than the actual problem domain, generic type systems are more of a problem than a solution. I don't use a hammer because I love driving in nails, I use it because it's the best way to stick two pieces of wood together. (edit: perhaps I should clarify that I'm referring to type hierarchies within the application itself as an intrinsic part of design, not language type hierarchies)
- masklinn 12y ago> It seems to me that people program heavily with types because that's what compilers are really good at. Therefore that's what most languages give us. But I don't want to be constructing huge, complex type hierarchies with every application That makes no sense, most languages with good generics support barely have type hierarchies (let alone complex one).
- NateDad 12y agoI must be using a different definition of a type hierarchy.... Don't C# and java both have generics and type heirarchies?
- 12y ago
- mserdarsanli 12y ago"If you think it's simple, then you have misunderstood the problem." Bjarne Stroustrup