6 ms·
I'm not even a Go developer, I just played with it a bit a couple of years ago and used it for a small one-off internal API thing, and I can think of a dozen re
by vec 9y ago
I'm not even a Go developer, I just played with it a bit a couple of years ago and used it for a small one-off internal API thing, and I can think of a dozen real-world use cases for generics off the top of my head.
* type-safe containers (linked lists, trees, etc.)
* higher order functions (map, reduce, filter, etc.)
* database adapters (i.e. something like `sql.NullColumn<T>` instead of half a dozen variations on `sql.NullWhatever`)
* 99% of functions that accept or return `interface{}`
I appreciate that they seem open to the idea for v2, but "the use case isn't clear" is absurdly out of touch with the community. Using `interface{}` to temporarily escape the type system and copy/pasting functions just to adjust the signature a bit were among the first go idioms I learned, and they both exist solely to work around the lack of generics.
- zemo 9y ago> I'm not even a Go developer > Using `interface{}` to temporarily escape the type system tbh if you program Go correctly, you use interface{} pretty rarely.
- camus2 9y ago> tbh if you program Go correctly, you use interface{} pretty rarely. It's a bit like saying "if you program C correctly, you use (void *) pretty rarely.". that's not the case, Go maintainers themselves keep on adding API with interface {} everywhere. Are you saying they are not programming Go correctly?
- spyspy 9y agoIt's generally the opinion of the Go community that map, reduce and filter are bad ideas due to how easily they are abused. A for loop gets the job done easily enough. If you've ever worked with data scientists working with Python, you'll quite often see them all chained together, probably with some other list comprehensions thrown in until it becomes one incomprehensible line.
- rbehrends 9y agoThe same argument applies, mutatis mutandis, to imperative iteration constructs such as range.
- pcwalton 9y agoIf that's the case, then the Go community is wrong. For loops do not get the job done easily enough. I've lost count of the number of times I've had to do contortions in order to count backwards inclusive down to zero with an unsigned int. With a proper iterator API, it's trivial. Furthermore, for loops are a pain to optimize. They encourage use of indices everywhere, which results in heroic efforts needed to eliminate bounds checks, effort that is largely unnecessary with higher level iterators. Detecting the loop trip count is a pain, because the loop test is reevaluated over and over, and the syntax encourages complicated loop tests (for example, fetching the length of a vector over and over instead of caching it). For loop trip count detection is one of the major reasons why signed overflow is undefined in C, and it's a completely self-inflicted wound. I'm generally of the opinion nowadays that adding a C-style for loop to a language is a design mistake.
- concede_pluto 9y agoIt's also strange that a language that wants to encourage parallelism requires for loops, and specifies that they always run sequentially. Java 8 can put map/reduce with a thread pool in the standard library precisely because it doesn't use a for loop; imagine how tedious and repetitive the Go version would be: https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html https://docs.oracle.com/javase/tutorial/collections/streams/...
- Sharlin 9y agoTo be fair, I don't think Go prioritizes parallelism as much as it does concurrency.
- fmap 9y ago> For loops do not get the job done easily enough. There was a nice paper at this years POPL which (in my opinion) allows you to substantiate this claim. The paper is "Stream Fusion to Completeness", by Oleg Kiselyov, Aggelos Biboudis, Nick Palladinos, and Yannis Smaragdakis. The actual question in the paper is how to compile away stream operations to imperative programs using for/while loops and temporary variables. On the other hand, if we look at the output of the compiler we can see how complex it is to express natural stream programs using only for/while loops. For instance, even very simple combinations of map/fold/filter create while loops and make it difficult to detect the loop trip count afterwards (in fact, you need an analysis just to detect that the loop terminates). If you combine several such streams with zip, the resulting code makes a nice entry for obfuscated code contests. Finally, if you use flatMap the resulting control flow doesn't fit into a for/while loop at all... So for/while loops are not simpler than stream processing primitives and unless you explicitly introduce temporaries (i.e., inline the definition of map/fold/etc.) you quickly end up with very complicated control flow.
- piinbinary 9y agoI would also love Result<Err,MyThing> in as a return type in place of (err, myThing)
- bjz_ 9y agoYeah, using a tuple for what clearly should be a disjoint union is infuriating. I really don't buy the gopher argument that 'it is hard to understand'.