For the record, if you want to avoid the creation of intermediate arrays, you can:
lst.lazy.grep(Array).flat_map(&:itself).sum
Not as clear, because the standard library doesn't have a `#flatten` method for lazy enumerators.But the point is the interface, not the implementation. Efficiency doesn't mandate assembly-like DSLs. Your interface could be as clear and clean as Ruby's and produce fast, inlined code by the power of macros. Ruby doesn't have macros, so chaining lambdas is the best it can do.
Ruby also has call/cc. None of the iterating methods has any provision to make them "safe" from it. They aren't safe from modifications to the iterated collection either. I think it makes sense; being forced to accumulate using only linked lists and having to be constantly on guard to support a rarely used quirky feature is a bad tradeoff IMO.
I dont think interfaces is the point. As it is now in ruby you have to pick between comfort and speed when you can have both.
Continuation safety has never been a thing in ruby, so caring about it doesn't make much sense regardless of the presence of call/cc.
And lastly, neither my loops nor others I have mentioned only accumulate into lists. My loops a re in the most general sense a left fold, although right folds are possible to write as well. I provide accumulators for just about any data type available, and writing a new one yourself is pretty easy. You can express lazy loops with it as well.
All without sacrificing performance. Any performance in most cases. I haven't written much ruby since the 1.9 days, but back then I remember having to rewrite the nice .each{}.blah.blah into for loops. I could prototype in a nice way which was nice, but in the code I ended up shipping I had to juggle state using for loops because the thing I prototyped ended up being a bit slow.
I use map, filter and friends in scheme all the time, but when those are insufficient or too slow I don't have to resort to named lets. I can just use the loop macro which compiles to a named let.