Good? It's an ugly hack with limited functionality (due to Go's design, not the developers' skill and good will). A good solution would be forking the reference compiler and doing a proper implementation.
The library is Go. What you're suggesting seems to be extending Go so that it becomes some other language derived from Go. Extending Go might make for a cleaner and/or better generics solution but if you have to have customized compiler to run the code then you're no longer running Go.
Historical tidbit: Pizza is the precursor to Java's own generics implementation (introduced in Java 5), both were written by Martin Odersky who then went on to create Scala.
- Generics (aka Parametric polymorphism)
- Function pointers (aka First-class functions)
- Class cases and pattern matching (aka Algebraic types)
13 years, and only it's three features has made it into Java
I wish Sun found a way to transfer the Java trademark to Odersky before dying.
Scala has so many nice features that companies prohibit because the language isn't called "Java".
I'm interested in Go but haven't looked into it yet. The fact that we're even talking about "generics" makes me nervous about further exploring it. Generic collections that have clean, dry implementations seem to be pretty much a requirement for new programming languages, in the way that core support for hashes is.
Just because there is no solutions yet, it does not mean you can just throw out any solution. I don't think code generation is a good solution for generics but I like the Linq feature though.
I really hope this will get solved in the language itself, I like Go quite a bit, but there are quite ugly places, all related to generics I guess:
- No min/max for integers (and Go doesn't have the ternary operator)
- No IsMember for checking if an object is in a collection
- Directly from the Gen page: Go’s sort package requires the fulfillment of three interface members, two of which are usually boilerplate. If you want to sort by different criteria, you need to implement multiple ‘alias’ types.
Also, unrelated to generics, but no multidimensional arrays.
The size has to be known at compile time, though. One can do a slice of slices, but then it's not necessarily continuous in memory. So you are left with allocating a one dimensional array of size x*y and doing index calculations by hand like in the good old 70's or something.
> I edited that part of the comment out because it was not really related to anything, but I meant that all identifiers go into a single namespace, e.g if you have a package called bytes you can't call a variable bytes, if you have a struct type called bytes, you can't call the instance bytes
This does not compile, list variable shadows the list package. I would much prefer doing list::New() for package access like in C++, and being free to use obvious variable names (all the time the most obvious variable name is also the name of the package).
Adding `::` just to separate package namespace adds nothing useful IMO; just more noise and one more needless concept.
If I decided to re-use the package name more than once it'd be `list1, list2`
I guess it's probably a programming culture thing, but I wouldn't use the word `list` to begin with. I'd use `l1`, `l2` etc. in the case where the name isn't important. It conveys no less information than `list` and short variable names AFAIK are already idiomatic so it's not even unconventional... But with all that said, `list2` wasn't a very good variable name to begin with. If you needed more than one list, then they clearly served different purposes and in that case it makes sense to name them as such: `apples`, `oranges`, `input`, `output`.
It's an example, not a real program, I do like however to call my variables "file", "path", "buffer" instad of having "f", "p" and "b" or "buf", especially when there is a lot going on in the algorithm. I don't think there is a lot of baggage in having a separate namespace for packages and being able to say:
To be fair, C++ doesn't have dynamic statically sized arrays yet either although you can get close with constexpr (but still done at compile time) yet.
Dynarray was slated for C++14 but has been pushed since it really isn't that useful and most people can get away with using vector.
I edited that part of the comment out because it was not really related to anything, but I meant that all identifiers go into a single (language-level, not program-level) namespace, e.g if you have a struct type called Bytes, you can't call the instance Bytes etc. I end up having to use a lot of ugly variable names.
This looks similar to an older generics system for Go, `got` (GO Templates). Got was pretty cool, but Go 1.0 broke it due to the parser getting stricter.
These higher-order functions are a very inefficient way to write loops in Go. When you chain them you will end up with multiple sequential iterations instead of only one. Sort should not allocate and return a new slice, it's better to sort in-place, etc.
It’s by design, though I understand the concern. From a design perspective, I like getting a distinct slice out the other end, without having to wonder whether I’ve mutated my original slice. It’s more stateless, so to speak.
Fwiw, slices are inexpensive by design. The elements themselves are not copied. Allocating a new slice is really a small ‘struct’ which serves as a pointer to the underlying array: http://blog.golang.org/go-slices-usage-and-internals
(Gen’ing pointers is supported, which mitigates the potential for allocation.)
It is true that chained operations will be multiple iterations. Whether it will net out to more iterations than otherwise depends on the use.
I’d be interested to see if someone can come up with a pattern where the operations themselves are composed, with a ’.Results()’ method that can intelligently (lazily?) minimize iterations. That’d be impressive.
That's functional programming for you. It's definitely less efficient, but there are other major advantages. For one thing, given the propagation of immutable data, things can be parallelized effortlessly - look at 'pmap' in Clojure for example. Once you're familiar with the style, it's significantly more concise and readable.
That being said, a systems programming language may not be the right place for FP concepts.
Very cool - I was not aware of this feature. Fwiw, I'm actually something of an FP zealot; I failed to make a stronger case in my comment because I'm tired of arguing, and I'm concerned that I'm being obnoxious.
Scala gets around this with "views": store the higher-order functions until the collection actually needs to be used and then apply them all at once, without any intermediate data structure.
D is a systems programming language with FP concepts and they work quite well. Also, it has generics / templates / parametric polymorphism that are more powerful and easier to use than C++.
Note that the Rust compiler doesn't do any stream fusion; rather the functional idioms are designed around iterators, which provide a functional interface that relatively easily and predictably compiles down to code that's as efficient as the corresponding for loop.
I wondered about that - Rust looks like the one systems programming language I would actually enjoy using, but I don't know enough about it to have an informed opinion.
Thanks for your effort. This is not about the library. Your site's mobile version is kinda broken. The left menu thingy always remain in the site and you can't read the main context. This happened to me on my Android Firefox Browser.