alt.hn

1/8/2025 at 11:15:25 PM

A visual demo of Ruby's lazy enumerator

https://joyofrails.com/articles/simple-trick-to-understand-ruby-lazy-enumerator

by rossta

1/11/2025 at 10:10:17 PM

When I learned Haskell in college I was blown away by how laziness enables cool things like dealing with infinite lists or more performance even though the UX is exactly the same. (Apparently with Ruby there is the slight hint of adding the lazy method in between)

Later I found out laziness in the whole system by default leads to some difficult issues, which quite a few people seem to agree with. Simon Peyton Jones (Haskell co-creator) apparently has said "The next Haskell will be strict". (https://news.ycombinator.com/item?id=14011943)

by afraca

1/11/2025 at 11:12:22 PM

Laziness is great for collections, and modeling the infinite but as a general model for programming it's a little loopy for my taste too ;-)

by drnewman

1/12/2025 at 3:20:35 PM

That was SPJ being cute more than an actual indictment of Haskell fwiw. That quote gets misused a lot.

Laziness hasn't killed Haskell's usefulness. However, it is something Haskellers take for granted. I can't tell you how many times they "just turn on -XStrict" and are surprised their program gets slower.

by whateveracct

1/11/2025 at 8:07:55 PM

Hm, the CSS and JS don't appear to load for me. Not even a <body><html> set of tags in the HTML response.

by adsteel_

1/11/2025 at 9:58:49 PM

Same here, both on computer and mobile. The rest of the website looks fine.

by fredrikholm

1/12/2025 at 1:21:56 PM

I have heard a few people mention issues but I haven’t been able to reproduce nor understand the scope of the issue. Any more details you can share? You’re getting HTML but JS or CSS assets aren’t loading, right? What status and headers do you see for static assets?

by rossta

1/11/2025 at 5:20:25 PM

Really cool visualization and neat to learn about lazy enumeration!

Excuse me while I go back through my code and make sure I’m using lazy enumeration wherever I’m iterating over large collections….

by Syntaf

1/11/2025 at 7:46:10 PM

This sounds like a similar response I had when learning about stream editors vs text editors. It was one of the killer apps that convinced to become a CLI warrior. Opening up a large text file in Notepad took for ever, but opening the same file in vim was a nothing burger. Then, the same person that showed me that showed me sed/awk/grep, and I was off to the races.

by dylan604

1/12/2025 at 7:49:04 AM

So in Ruby, `map` and `select` are eager-by-default, but you can just write `lazy.map().select()` to make the whole chain lazy? That's really nice - much better than Python 2, which was also eager-by-default and you had to change every function call to make it lazy (`map` => `imap`, `filter` => `ifilter`).

Python 3 changed to being lazy-by-default. I assume that improves CPU/memory usage, but in some cases it does have less predictable behaviour. I can see why Ruby, with its goal of "developer happiness", would choose to retain the predictable behaviour of eager-by-default.

by pansa2

1/12/2025 at 8:20:48 AM

Swift does this too, with almost the same syntax. IMO it's the right choice.

by saagarjha

1/11/2025 at 6:55:44 PM

Lazy enumeration can also save memory, because you aren’t storing entire collections during intermediate steps, and it works with infinite/unknown size collections. Such as streaming data.

Some examples:

I wrote a utility gem a while ago that lets you lazily intersect, union, etc various potentially infinite streams of data. https://github.com/maxim/enum_utils/

I also used lazy enumeration for traversing the wordmap in my no-RAM static storage gem. https://github.com/maxim/wordmap/

by hakunin

1/11/2025 at 8:40:13 PM

In the worst case, that must have intermediate space requirements equal to the entire collections, right?

by hansvm

1/11/2025 at 8:59:02 PM

I don’t think that can happen because all those functions assume the streams are consistently sorted.

by hakunin

1/11/2025 at 9:18:17 PM

Ohhhhh, nice. Yeah, sorted data is powerful. Thanks for pointing that out.

by hansvm

1/11/2025 at 9:15:35 PM

How is it different than a window, rolling window?

by pyinstallwoes

1/11/2025 at 9:29:21 PM

It's probably a version of that. But since data is assumed sorted, memory requirements almost never grow beyond one item per stream.

by hakunin

1/12/2025 at 11:47:41 PM

Java Streams and Kotlin Sequences provide similar iterator capabilities. Iterators are great for this lazy performance but can sometimes be difficult to debug. Especially if you are nesting many iterators, then extracting the underlying collection can be complicated. But necessary in many workflows.

by ryangs

1/11/2025 at 4:54:36 PM

I was expecting a visual comparison towards the end of the article, where you would be able to click a button and both the eager and lazy versions would start executing simultaneously, one displayed next to the other, and you would clearly see that the lazy one completed earlier. This would make it even more obvious how the lazy one is faster.

Nevertheless, this was great.

by endorphine

1/11/2025 at 7:44:04 PM

Thanks for the feedback. I was thinking along those lines but settled on a version that let you toggle between the two. I’ll keep this in mind for next time though.

There are probably a lot of fun variations to explore. Since this post seemed to resonate, I may be motivated to try some more experiments.

by rossta

1/11/2025 at 9:38:53 PM

I find horizontal/vertical is usually confusing (not to you obviously). Here is an example: https://www.investopedia.com/terms/h/horizontalanalysis.asp Maybe easier to stick with the lazy/eager wording?

by robocat

1/11/2025 at 10:42:09 PM

That’s fair. I acknowledge that terms like "horizontal" and "vertical" may be overloaded or even confusing, in this case, if it’s difficult to see the connection with the visuals. This is somewhat part of the risk in trying to explain a concept in a less-than precise way to introduce a new concept.

by rossta

1/12/2025 at 7:08:06 AM

I love the visuals - they are fantastic at showing the difference.

If the visuals were vertical then the filtering might look more natural because time would be left-to-right and balls would have natural gravity and fall "down" through filters? Code runs top to bottom so I'm guessing it would still be clear.

And putting a number in each of the balls might help clarity too :-)

The only crazy thing is that Haskell lazy is pull (right) whereas Ruby lazy is still push - so the lazy keyword is somewhat confusing but that can't be fixed.

I am not criticising and certainly don't want to make unnecessary work for you. Graphic design and animation are dark arts!

by robocat

1/12/2025 at 1:10:09 AM

Your site is broken...

by Exuma

1/12/2025 at 1:23:09 PM

Bummer, I can’t reproduce. Could you share more details?

by rossta

1/12/2025 at 8:45:47 AM

Apparently Typescript doesn’t have anything built-in like this?

by lukasb

1/11/2025 at 4:39:01 PM

That's lovely and makes it very obvious what's happening.

by Lio