3 ms·
This is the textbook definition of the Blub Paradox[1]. If you've mostly used Go (or moved to Go from JavaScript before it had iterators, or from Java where ite
by unscaled 2y ago
This is the textbook definition of the Blub Paradox[1]. If you've mostly used Go (or moved to Go from JavaScript before it had iterators, or from Java where iterators are a royal PITA to write), it won't make sense. That's okay, since it is often hard to imagine how a feature will be used without getting used to it yourself. I'm pretty sure that most FORTRAN 66 developers coming to Go would be puzzled on why you need for loops at all, when you can write DO loops and specify the line number where the loops end (older Real Programmers[2] don't even understand why you need loops at all, since you can always GOTO anywhere you'd like).
So to cut it short, iterators, as Go implements them, should be useful at least for the following cases:
- Iterating over custom collections (e.g. trees, concurrent maps, queues) that are not provided by the language (and "range for" doesn't have custom code for inside the compiler).
- Iterating over a collection in a different way, for instance filtering out some elements or iterating over the collection backwards (as in the giving example).
- Reification - if abstract iterators can be passed to functions (instead of actual slices), you can write functions that operate on a theoretically infinite stream.
- Chaining iterators. If iterators can be reified, you can also chain them together. This is somewhat cumbersome with the syntax Go 1.23 will offer, but in many languages you can write code like this:
let incompatibleTransactions = user.Accounts
.Filter(account -> account.Balance <= 0)
.FlatMap(account -> account.PendingTransactions())
.Filter(tx -> !tx.AllowCredit())
Once you know what each function does, it is clear that the code goes through all the accounts that have a zero or negative balance and returns all the pending transactions that do not allow credit from these accounts.
The equivalent imperative code is harder to figure out at first glance
incompatibleTransactions := []Transaction{}
for _, account := range user.Accounts {
if account.Balance < 0 {
for tx := range account.Transactions {
if !tx.AllowCredit() {
incompatibleTransactions = append(incompatibleTransactions, tx)
}
}
}
}
If the accounts and transactions collections are not built-in the iteration code would even look worse. This code is harder to read since it conflates the What (what we want to achieve with the code) with the How (how to implement this with a for loop). Obviously, this is what imperative programming is all about, and Go is indeed becoming less imperative.
[1] http://wiki.c2.com/?BlubParadox http://wiki.c2.com/?BlubParadox
[2] https://sac.edu/AcademicProgs/Business/ComputerScience/Pages/Hester_James/Real%20Programmer.htm https://sac.edu/AcademicProgs/Business/ComputerScience/Pages...
- neonsunset 2y agoYup. This is why I'm despairing so much over Go's popularity after using C#/F# and Rust which have rich and idiomatic iterator APIs. Go implementation is plain ugly, flawed and, most of all, is going to be slow unless you write it in the most verbose way due to Go's compiler weakness. There are languages that move us forward, Go sets us back by 20 years.
- Karrot_Kream 2y agoSome people enjoy expressiveness in their programming language. Some people don't. Some people like both, I'm one of them, and for some programs I choose expressive languages like Haskell or Common Lisp and for others I use unexpressive languages like Go or Zig. Take these things a little less personally. Live and let live. People think differently from you, and that's okay.
- neonsunset 2y agoThis is not about personal choice but rather Go's undeserved adoption in domains it has absolutely zero business being applied to. This leads to me to generally approach engineers promoting it as misguided and severely lacking in some area of knowledge the moment Go is suggested to be used anywhere beyond light networked microservices or CLI utilities. Instead, people shoehorn it into data processing and databases, the domain at which .NET is incomparably more adept due to performance primitives it offers, if we still talk high-level-ish languages with automatic memory management. Of course if there is no such requirement, there are many (like Zig, Rust and C++) systems programming languages that are better in every possible way at solving the task. And yet, we get Go and startups struggling to scale. But all the interesting problems in which Go is attempted to be applied to, where the solution, if successful, is despite Go not because of it, would have benefited from C#/F# which offer much better control and performance assurances, without having to fight the tool.
- Karrot_Kream 2y agoTake these things a little less personally. Live and let live. People think differently from you, and that's okay. I have meticulously benchmarked Go in previous roles and also used Go as a load generator and with smart allocation strategies the language is quite fast. I think you're letting your emotions cloud your judgement but that's nothing new in PL discourse. There's no better way to bring out those that identify with/against programming languages than PL discourse.