12 ms·
Coming from JVM languages, it drives me nuts that I can't .map/.filter/.foreach/.reduce etc. my collections, especially with something like streams/sequences. T
by RhodesianHunter 8y ago
Coming from JVM languages, it drives me nuts that I can't .map/.filter/.foreach/.reduce etc. my collections, especially with something like streams/sequences. That's where you really notice the lack of generics if you're used to this sort of programming.
- chewxy 8y agofunny thing I wrote this on the morning commute to work - https://twitter.com/chewxy/status/1105962162021756928 https://twitter.com/chewxy/status/1105962162021756928 Not that I'm saying that Go should not have functional features - it does, but it also forces you to think more deeply on things.
- nemo1618 8y agoCheck out my experiment with adding map/filter/reduce to Go: https://github.com/lukechampine/ply https://github.com/lukechampine/ply Ultimately I concluded that map/filter/reduce really need to be paired with a concise lambda syntax in order to be ergonomic. Writing out a full func() literal doesn't feel much cleaner than just writing a traditional for loop. However, adding a new lambda syntax would be a much larger undertaking than I can manage right now. The other thing I concluded is that you can highly optimize map/filter/reduce chains if they're first-class citizens of the language, rather than living in a userspace library. I was able to compile such chains into for loops that are more efficient than what a novice might write, and no worse than what an expert would write. The only way to improve would be to inline more aggressively, i.e. inline "x += 2" instead of calling out to "addTwo()" on each iteration of the loop. I think there's an unfilled niche in programming languages that's basically "Go plus some FP niceties." I love Go's simplicity, tooling, and performance, but writing endless for loops and error-handling blocks gets tiring and can obscure the operation you're actually trying to achieve. At the same time, jumping to full-blown generics, macros, etc. like Rust introduces too much "magic," hurts readability, and bloats compile times.
- jonahx 8y ago> I think there's an unfilled niche in programming languages that's basically "Go plus some FP niceties." Nim?
- krapht 8y agoF#? Runs on .net, interops with the entire .net ecosystem, has high performance garbage collector, if you need high performance you can use stack-allocated data structures.
- ilovecaching 8y agoRust actually has a lot of Gos spirit in terms of being practical and consistently engineered, but also embraces FP. The issue is that Go is philosophically tied to concreteness. You solve your specific problem each time from scratch. FP is about raising your problem to a higher level of abstraction and solving it there. In Haskell this is you taking your domain and raising it into a problem of category theory, and then using all the nice things we know about transformations in category theory to solve the abstract problem and lift it back down to earth, such that we can take advantage of any sort of mathematical, general solution. so in a sense Go + FP is like adding two diametrically apposed philosophies.
- dnautics 8y ago> FP is about raising your problem to a higher level of abstraction and solving it there Haskell and lisp are like that for sure, but more blue collar FP languages like erlang ate "basically FP so that you get memory safety and easy multithreading".
- pyrale 8y agoI get paid for haskell and I don't use category theory. No one in my team does and neither do a significant share of the people in the industry. I don't know what outsiders think about us, but 90% of the value derives from the simple things : constructing simple datatypes easily, a world-class type checker and some great libs that require little knowledge to be used, like Servant or Aeson. Sure, there are fancier things if you want to go beyond that, but you can be productive with the bare minimum of Haskell, as Elm shows.
- boyter 8y agoAgreed. I was just bitching about that on twitter. I was just working through some code to check for the intersection of two lists and use the result to iterate though. Creating new slices to put values in with loop in loops is not a productive use of my time. I don't really want generics personally, I would just like some magic methods on top of the existing slice/maps in Go. They already are magic in the way they work so why not provide those few helper methods and solve a massive pain point I have with Go.
- ilovecaching 8y agoWhat magic? Go is very unmagical, and that’s the way it should be. If you need to merge two lists you can just write a method that does that. Publish it as a package and reuse it. In Go algorithms should be apparent. Go is a code heavy language, not data heavy. You should see and understand the real cost of your solution.
- tsimionescu 8y agoWell, if you had generics, you could do that. Without generics, you get to either (a) write an efficient method that merges 2 lists of Foos, which is not really package-and-reuse material, or (b) write a horribly inefficient method that merges 2 lists of some interface type, forcing your users to copy their data to new slices every time (since an []x is never an []y). Faced with these 2 wonderful options, most people simply decide to copy or write again the same piece of code...
- ilovecaching 8y agoCopying is encouraged. Like I said, having the algorithm there is a good way to make it apparent what the code is actually going to do and the associated cost of the solution. interface{} could be avoided by having an interface that reflects the behavior you actually need from the types involved in the algorithm. If you need to only test for equality, you could have an algorithm that works on []Eq. That is one of the downsides to Go, unlike Haskell, interfaces are usually defined by the consumer, which makes negotiating common interfaces like Ord and Eq difficult.
- ilovecaching 8y agoGo isn’t Java. It’s easy to bring our biases in from other languages, but when you use a language you should be buying into the philosophy, conventions, and style of the language as much as the rules of the language. Go focuses on code, not data and concrete solutions, not generic ones. It’s a language designed for the 90%. If that doesnt fit your requirements, it’s ok to use C++, Haskell, or Java, or some other equally good language. But Go is really, really good when you give it a fair chance.
- tybit 8y agoMap, filter and reduce are for the 90% though.
- ilovecaching 8y agoMap filter and reduce are generic tools that can be accomplished through constructs Go already has. The point of Go is that most applications do not need a high level of abstraction, they are bounded problems. Go is also reflecting the Unix philosophy, no surprise given its authors, of building small focused tools. Therefore framing problems in terms of generic data transformations facilitated by mapping and filtering is drawing attention away from the concrete solution and making the code less clear.
- coldtea 8y ago>Map filter and reduce are generic tools that can be accomplished through constructs Go already has. They can also be accomplished through constructs Brainfuck already has. Actually any Turing complete language will do. >Map filter and reduce are generic tools that can be accomplished through constructs Go already has. The point of Go is that most applications do not need a high level of abstraction, they are bounded problems. map, filter and reduce are not "high levels of abstraction" any more than for or channels are. >Therefore framing problems in terms of generic data transformations facilitated by mapping and filtering is drawing attention away from the concrete solution and making the code less clear. The "concrete solution" being copy pasting code with a different type to filter a list for your types, and using a for loop instead of filter or map? Sounds more like Stockholm Syndrome.
- deleted 8y ago[deleted]
- cies 8y ago<deleted as I misunderstood the parent, thanks for pointing it out>
- fnord123 8y agoYou can do it in Java. I think GP is talking about the inability to do this in Go.
- eternalban 8y agoI come from JVM as well. https://play.golang.org/p/kbmrIvoQBXs https://play.golang.org/p/kbmrIvoQBXs If you want true streams and don't mind the performance hit, you can certainly design a library to implement those semantics on top of Go channel types.