7 ms·
It's sad that such basic stuff took this long. If we're lucky we might even see a `Map` function in our lifetimes.
by silverwind 2mo ago
It's sad that such basic stuff took this long. If we're lucky we might even see a `Map` function in our lifetimes.
- wannabe44 2mo agoMap function leads to poor code in Go. Function literals are verbose and inlining is far less agressive. It simply isn't the way of the language. Even python shuns map and filter in favor of comprehensions. A for loop is more readable than the lambda soup.
- ninkendo 2mo agoIMO it depends on the language… to me, map/collect/etc are useful in languages that have the concept of immutable data, because you can initialize an array with a single call chain, and be sure that nothing after that can modify it. What I’ve seen in the “for loop” approach that I can’t stand, are things like (pseudo code) var a = [] for x in coll1 { a.push(foo(x)) } do_stuff_with(a) // … further down the function for y in coll2 { a.push(bar(y)) } do_other_stuff_with(a) Reading code like that, is the first call to do_stuff_with(a) a bug, because it’s not fully built from both coll1 and coll2 yet? Or is the second call to do_other_stuff_with(a) a bug because a now contains more stuff than the developer probably thought? Can I safely move both loops next to each other, or does that break something subtle? If I need to pass a to a new function, where can I safely do this? Before or after I add from coll2? (In my actual times seeing this, a is really a map of cached key/values or something, and it’s kinda ok that the contents were different each time it was used, but subtle bugs emerged…) IMO the sane way to do it is to just not incrementally mutate things like that, and stick with giving things a single place where they’re defined and initialized. Go doesn’t really help you here because there’s no such thing as immutable data. So just adding Map/collect or whatever doesn’t really buy you much.
- tialaramex 2mo agoOften the mutation might have performance benefits. Of course if you're Rust the stdlib and compiler might conspire to optimise an operation you wrote which reads as non-mutating into an actual mutation which was faster. This is another benefit of the "destructive move". If I consume X and spit out Y, the X is gone, so it's OK if secretly I just mutate X and tell you that's Y now.
- troupo 2mo agomap functions are very useful for iterating over collections. Most functions iterating over collections are useful, because a lot of the data you're commonly dealing with is collections. And most collections are generic. > Function literals are verbose and inlining is far less agressive. > Even python shuns map and filter in favor of comprehensions. That's the problem of the language design. And Python isn't the best language to turn to for language design > A for loop is more readable than the lambda soup. A for loop shoving modified items into a temp variable with append() that is then returned is less readable than a map function transforming data. Too bad Go decided to turn lambdas into unreadable soup.
- TheDong 2mo ago> A for loop is more readable than the lambda soup. Let's assume you have a slice of strings you want to uppercase. Which of the following is more readable? uppercased := slices.Map(inputSlice, strings.ToUpper) // or uppercased := make([]string, 0, len(inputSlice)) for _, s := range inputSlice { uppercased = append(uppercased, strings.ToUpper(s)) } Let's say you want to parse a bunch of user-given inputs into durations, surely the following is more readable? parsed, err := slices.MapErr(inputstrings, time.ParseDuration) I think map functions lead to cleaner code when used like the above, and a lot of for loops end up falling into those patterns.
- wlamartin 2mo agoI think in a language designed around FP ergonomics and expectations there's a lot to like about it. In your second example, as a retrofit, I find myself asking "when does MapErr stop consuming the input list?", "which error gets returned if multiple errors could be returned?", "is it a errors.Joim situation", "if there are multiple errors how do I map them to the failed elements in parsed", "if I did want each parse to have either success or fail (think Result type) how would I represent this generically in a language that favours multiple return types" There's a lot going on with that example that a for loop makes explicit and flexible for other choices.
- tyre 2mo agoPython uses comprehensions because whitespace sensitivity was a horrendous language decision, then couldn’t find a way to support multiline lambdas. Comprehensions are not a well-designed feature but a consequence of poor design.
- pjmlp 2mo agoNope, as someone there at the time, they are an influence how language like Haskell do them. Which by the way has no issues being whitespace sensitive and having multiline lambdas. The only reason Python doesn't support them is Guido not wanting to have them.
- wannabe44 2mo agoComprehensions are way cleaner and more optimizable for the common case.
- PrimalPower 2mo agoThe beauty of go is YAGNI. Language design makes it much harder for people so do stupid and cute things. During my design process if I start realizing that I’m missing maps, More expressive Types, Or more complex polymorphism. I ask myself if I really need those things. If I really do. I move off of go. That’s the beauty of the language. Go does not need more complicated language features because it’s can handle the majority of trivial software work without unnecessary complexity. The language does not need to solve complicated problems.
- brokencode 2mo agoOk, and what if you realize you want these things a million lines in? Do you still move off of Go? Generic programming isn’t some fancy research language feature like dependent types. It’s just a bare minimum feature in any modern typed language. It’s perplexing that after C# and Java both notably shipped without generics initially then added them later that they decided to ship Go without generics.. only to end up adding them later.
- improgrammer007 2mo agoThis. One should never pick a language that regresses in terms of features from the get go.
- tialaramex 2mo agoI guess it's possible that C# and Java taught the wrong lesson (you can add this later) and that actually reduced the impetus to ensure Go shipped generics in 1.0 It is also entirely fair to say there's a lot of complexity here and so there's a risk you exceed your complexity budget which for Go as I understand it was very slim. It is a possible a Go 1.0 with more generics doesn't take off because too many people bounce off the extra complexity and so a decade later it's an obscure thing Google made once that has a few fans but not much adoption. Or that extra complexity means Go 1.0 ships five years later, after Rust 1.0 has given people an appetite for better performance and better safety and its sharpest corners have already been knocked off.
- bborud 2mo agoThis is also why people eventually leave languages. Satisfy everyone’s wishes for long enough and you get lots of different styles of doing things and … «wow look at that much simpler language over there; let’s try that instead»
- inigyou 2mo agoGo's whole philosophy was to keep the language simple. It's a shame they're abandoning that now and becoming the next C++/Zig/Rust/Java
- troupo 2mo agoThey threw many babies out with the bathwater chasing yhe rather unspecified "simplicity" and making parts of the lsngusge more complex to use as a result.
- pjmlp 2mo agoTurns out programming languages are complex for a reason.
- inigyou 2mo agoBut diversity is good. If I want C++, I already know where to find it.
- pjmlp 2mo agoThe fallacy of "simple" languages is not understanding the history of programming languages, why and how they grow with the community, assuming they get any adoption at all. No one among the folks that created Scheme or C, would assert R7RS or C23 are that simple.
- 9rx 2mo agoThose who held that philosophy (Thompson, Pike) are now retired. Those who still have careers ahead of them want to have something to do. The natural consequence of a "bullshit job" economy.