7 ms·
These sorts of posts are profoundly boring. I know people will up arrow it -- some sort of spiteful "Down with Go!" contrarian thing, when they aren't talking u
by personZ 13y ago
These sorts of posts are profoundly boring. I know people will up arrow it -- some sort of spiteful "Down with Go!" contrarian thing, when they aren't talking up rust -- but it isn't because the content is interesting or illuminating, but rather as some sort of activist thing.
This particular piece (by a high school student, as an aside) starts off trying to create a surrogate for generics in Go.
Don't.
Here's the thing -- most of these posts are not about people making real code, but people making -toy- code. Where every function is all things to all people.
The number of times I've needed a generic abs in my life -- zero.
The number of times I've needed a double floating point abs in my life -- every single time.
That's the thing about generics and real, actual world code: Your types are generally much less amorphous than you think. They really are. This illusion that everything needs to be everything just does not hold in the real world.
But it is always the tiring example used against Go. Boring.
- azth 13y ago> The number of times I've needed a generic abs in my life -- zero. What about a generic max() or min() function?
- cgh 13y agoOr a generic list, vector, map...
- personZ 13y agoGo's native synonyms of lists, vectors and maps are already "generic", so I'm not sure what your point is.
- cgh 13y agoExcept the containers aren't typed. They are essentially containers of void*. If you believe that to be "generic", then you don't understand the topic.
- personZ 13y agoThis is simply wrong, and you clearly don't understand Go (which, as we've amply seen, doesn't stop people from pontificating about it).
- cgh 13y agoYou are right, I overlooked the magic of Go's build-in containers (I admit, I haven't touched the language after we looked at it around a year ago). I amend my comments to apply to user-defined containers and types, where generic == interface{}...at least, it did when we tried the language out. This is an example of a simple "generic" in Go, as I recall it: type mytype struct { mydata interface{} } The casting this requires felt like a step into the past when you're used to eg the STL.
- eridius 13y agoA generic abs? Not particularly useful, you're right. But he was using that as a trivial example. Generics are incredibly useful in a lot of contexts. One context that the author touched on briefly is new container types. In Go, if I have a Slice, the type of element the slice contains is specified. But if I have a user-defined container, either the container has to be specialized for a single type (which makes it largely useless, at least as reusable code), or it has to take interface{}, which really sucks. No more homogenous container, no more static type information when working with this container, etc.
- burntsushi 13y agoTrivial examples are terrible as evidence to support a point. Trivial examples are generally good for pedagogical purposes, which doesn't really fit with the OP. For example, the OP mentioned that using a stack in Go requires casting from `interface{}`. But this is patently ridiculous. Most people who need a stack in Go just use a slice: https://code.google.com/p/go-wiki/wiki/SliceTricks https://code.google.com/p/go-wiki/wiki/SliceTricks --- Is this a bit messier and limited than a container type suited to stacks? Yes! But it gets the job done the majority of the time. Therefore, it's not as big of a problem as the article leads you to believe. Not all things require clean polymorphic container types. Sometimes you can get by with less. And when you need more, you're going to feel a bit of pain with a less expressive type system. It's all part of the trade off. But it's not good to represent this as a scenario where it's all just bad stuff all the time.
- eridius 13y agoIt's more than just feeling pain when writing code. Using interface{} has a runtime cost. Both because of the vtable and because it requires heap-allocating something that could otherwise be inline.
- burntsushi 13y agoYes, that's true. The "pain" I had in mind wasn't in using `interface{}`, but in writing non-generic code. This doesn't result in a performance loss, but will result in some code duplication. (Or alternatively, extra complexity from using some sort of code generator.) But, to be fair, in the Go world, both mechanisms are used. It depends on which costs are important.
- 0xdeadbeefbabe 13y agoThe same sort of sales pitch goes for using no-sql because it's so flexible. But as time goes by you settle on a data model and it turns out you don't need flexibility as much as consistent data or services that scale well.
- rwallace 13y agoGeneric abs is an unrealistic toy example, sure. A much better example is an extensible array (a.k.a. vector a.k.a. list). This is the most basic data structure in all of programming, the first data structure needed in almost every program I write, and to be honest, I am of the opinion that a programming language that doesn't provide this has no reason to exist in the twenty-first century unless it was grandfathered in from the twentieth.
- kyrra 13y agoFun enough, a list[0] in Go is actually a doubly linked list. Resizable slices[1] are built into the language. Though, this leads to C style coding that some people thing is annoying (assigning the result of append back to x, since it could allocate a new array). x = append(x, a, b, c) [0] http://golang.org/pkg/container/list/ http://golang.org/pkg/container/list/ [1] http://golang.org/pkg/builtin/#append http://golang.org/pkg/builtin/#append
- worklogin 13y agoI can imagine generics being useful if you create large amounts of context-aware types, like was discussed in an HN post a week or so back.
- EvenThisAcronym 13y agoThe number of times you'll wish you had a generic red-black tree or linked list in your life: many, many times. The number of times you'll need a generic map or fold algorithm to operate on those structures: many, many times.
- grey-area 13y agoYou could easily define an interface and write your red black tree once for all types, you'd just have to wrap basic types like int to conform if you want to add them (most often this sort of list is of a custom data type though). e.g. https://github.com/petar/gollrb https://github.com/petar/gollrb So if you need a data structure like this, you can do it without much trouble without generics. Perhaps you don't feel that solution is as clean, but it's certainly pretty easy to do. NB that golang has not ruled out generics, it's just not something they felt compelled to put in initially, and not many people who use the language miss them.
- joeshaw 13y agoI posted a comment about this to the blog, but I released a tool which will generate type-specific source code from a generic definition. Code is at https://github.com/joeshaw/gengen https://github.com/joeshaw/gengen The abs example could be reduced to: import "github.com/joeshaw/gengen/generic" func abs(x generic.T) generic.T { if x < 0 { return -x } return x } You could then generate different type-specific versions: gengen abs.go int32 | gofmt -r 'abs -> absInt32' > abs_int32.go gengen abs.go float64 | gofmt -r 'abs -> absFloat64' > abs_float64.go ... The downside is that the API is annoyingly non-generic (a different abs variant for each type) but at least you didn't have to type it in a bunch of times. I agree that abs() is kind of a toy example, but this approach has helped me a lot for various slice operations like indexing and deleting.