Hacker News new | ask | show | jobs
by killbot5000 2464 days ago
The simplest example I can think of is: Map(slice, func)

You can can implement this generically in Go using interface{} types and runtime type checking, but then you have runtime type checking failures.

A java/c++-esque "generics" implementation would be able to type-check at compile time.

1 comments

You can implement it in Go using loops, and it's not significantly slower or more error prone.
Unless you want to implement that on top of your custom structure, like, for example, b-tree. Then you either need to write N different implementations for each separate tree or you need to use `interface{}`.
Yes, custom containers are one place that generics are very useful.

Go has the most useful containers built in. Most code I write doesn't need custom containers, even in languages with templates (I write far more C++ and Java than Go) -- so I find that I don't miss them much when I spend time in Gopherspace.

The most egregious missing container is "set", coming from Python (as many Go developers do). After debugging, reviewing, and writing at least 3 different local implementations of a set, I can't wait for generics so that it can be written once and then never looked at again.
I'm slightly surprised you found three different set implementations - `map[T]struct{}` is the idiomatic one i see everywhere.

I suppose it's not sorted or concurrent-safe?

I mean that people make their own per-file or per-package set implementation for their service. There's no point putting it in a common utility package even within the same company, because it's specific to the type of what they're storing.

`map[T]struct{}` is only a type, it's not an implementation. You still need a handful of methods, that might be named inconsistently in each implementation by different developers. I will be happy when I never have to think about this again

> I'm slightly surprised you found three different set implementations - `map[T]struct{}` is the idiomatic one i see everywhere.

Set storage is not really the concern here, it's the set-theoretic operations which make sets useful (generally speaking, there are cases where all you need is the set being a set e.g. deduplication).

So I wouldn't be surprised that GP found several different implementations of union, intersection, difference, symmetric difference, subset, superset, …

Yeah but you can't implement it generically.

That means for every conceivable input type and output type combination you have to have a new MAP or REDUCE function to handle it.

All Modern languages except golang and elm only require one implementation of MAP that can handle all type combinations.

It's called parametric polymorphism.

Elm has parametric polymorphism.
you're right. My mistake.
Java is one example of modern language without proper generics. They have syntax sugar for Object references, but you can do almost the same with golang using interface{}.
I'm not sure what you mean by 'proper generics', but Java does have compile-time generics, ie List<T>, <A, B> B foo(A bar), etc.
Proper generics would allow you to parameterize with all types including primitive ones, not just Objects. Check out java.util.Arrays class as an example of why Java's generics are not proper: https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.h...
You've got a kind of made up definition of 'proper'. Java has generics, they don't have the best implementation of it I've seen, but I wouldn't call it 'improper'. It's just not a word that has any specific meaning in this context.

I seem to remember an article being written a while ago that found Java's type system, with the addition of generics, was unsound. Maybe that's what you're trying to say.

Yes, I know what it's called. I have implemented generics in compilers. I still don't miss them in most go code, in practice.