Hacker News new | ask | show | jobs
by duped 1848 days ago
That's just bad design - iterators and sequences need to be lazy. The intermediary type should not eagerly create large arrays on the stack, it should only ever do real work once the iterator has been driven.
3 comments

No, they don’t need to be. They can be. Go wasn’t designed as a functional language but to be fast to compile, fast to execute, zero dependency binary and simple syntax. It achieved that by a mile.
Implementing iterator combinators by eagerly evaluating them into temporaries is a bad, naïve design that results in the issue illustrated above.

A much better design is to do it lazily which is possible if you can store closures as fields of a data structure.

Not sure what fast compilation and execution or dependencies has to do with this. Implementing iterators that way is the worst possible solution that results in slow execution that can blow up the stack and crash a program. It would be better not to have iterators at all than to require them to be eagerly evaluated.

You can support functional features without being a Haskell...

Yes, lots of science. Go has slices which require specifying a size and you iterate over them using a for statement. You want lazy, pop in a channel and do it lazy.
This isn't "lots of science" it's rudimentary software engineering...

Sending data through channels just to implement an iterator seems insane. It's not strictly lazy either...

Why do go developers reject simple patterns that make faster code?

How are those magical lazy operations implemented in other languages? Someone had to take that insane step. It’s just not by default in go.

Look, I’ve written lots of scala and erlang so I get your argument. It just does not exist in go. And that’s okay.

Never got caught thinking “gee, need a lazy collection”. Maybe a stream when reading stuff from the ether. In go, channel was enough. 5 minute job. Nothing insane.

They're implemented with closures, not passing things through FIFOs. It's not magic. You barely need a compiler pass to implement the sugar for `for` loops: it's a trivial transformation to a `while`.
That’s probably okay if the code is I/O bound anyway, but in Go it will run a lot slower than doing multiple steps within a single for loop.

For loops may be unfashionable but they aren’t hard to read.

I don't find iterator combinations hard to read. Especially with postfix methods.

I do find deeply nested for loops with outer variables that might start uninitialized or need to be mutable much more difficult to read.

Sometimes moving an inner for loop to a separate function (that will likely be inlined) is better to explicitly show its inputs and outputs.
I agree they need to be lazy. This is why it's problematic - Go is only adding generics and not laziness.