Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

And in Clojure, Rust, Scala, Java... With sequence combinators being lazy in almost all languages that have them, writing complex folds isn’t usually a very good idea if the same thing can be achieved in discrete map/filter/etc steps.


Are they? I tried understanding how that worked a few years ago and it led me to something called "stream fusion" which seems like a magical set of code rewriting rules that wasn't even on by default in haskell[1].

For example if you did a map of x times 2 then map again with x times 2, I expect a single map of x times 4 without using temporary buffers or multiple passes for the intermediate map (this is a simple example, but gets more complicate once you throw in other stream operators).

I know java didn't do this when I was looking at their collectors source code back then.

[1] https://stackoverflow.com/questions/578063/what-is-haskells-...


It's not direct, as in Haskell, but it's there and used. Java has Streams, Kotlin has sequences, Scale has Seq, Rust has iter, etc. Lazyness is useful for iteration so languages with reasonable modernization make it readily availible in that context.


Stream fusion is only necessary for otherwise strict data types (like text, bytestring, vector, etc). Regular haskell lists will be 'fused' by default due to laziness, although the standard library does also fuse repeated list operations into an even more streamlined representation. However, this can be seen as more of a compiler optimization than anything, as it doesn't change the runtime complexity or the space complexity. Mapping over a list however many times always takes O(1) space, due to laziness.


Regardless of stream fusion, it will always be one pass in Haskell because of laziness.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: