# Lazy.rb 0.2

**URL:** <https://www.ruby-forum.com/t/lazy-rb-0-2/97140>\
**Category:** Ruby\
**Created:** [December 11, 2005, 6:52am UTC](https://www.ruby-forum.com/t/lazy-rb-0-2/97140 "2005-12-11T06:52:47Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![mental](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/c77e96/32.png) [@mental](https://www.ruby-forum.com/u/mental)\
**Post date:** [December 11, 2005, 6:52am UTC](https://www.ruby-forum.com/t/lazy-rb-0-2/97140/1 "2005-12-11T06:52:47Z")

</div>

Now that I’m done asking stupid questions about iterators, it’s time for  
another release of lazy.rb!

== WHAT IS THIS THING? ==

lazy.rb is a library which provides lazy evaluation for Ruby. It allows  
you to optimistically defer computations until they are required.

These deferred computations are represented by “promises”:

prom = promise { 2 \* 3 }  
p prom #=\> #\<Lazy::Promise computation=#Proc:removed\_email\_address@domain.invalid:1\>  
result = demand prom  
p result #=\> 6

A promise is only evaluated once, after which it becomes essentially  
indistinguishable from its result object:

p prom #=\> 6  
p prom.class #=\> Fixnum

In fact, you can simply use the promise directly and it will be  
evaluated for you automatically:

prom = promise { 8 + 1 }  
num = prom \* 2  
p num #=\> 18  
p prom #=\> 9

There’s one caveat; Ruby always considers promises, evaluated or not, to  
be true. If you are testing a result for truth, you must unwrap the  
result with demand.

prom = promise { false }  
demand prom # force evaluation  
p prom #=\> false

puts “wait, it’s true?” if prom #=\> wait, it’s true?

puts “no, false. much better.”   
unless demand( prom )  
#=\> no, false. much better.

Conveniently, calling demand on an already evaluated promise (or even on  
a regular object) is harmless.

p demand( 6 ) #=\> 6

== WHAT’S NEW THIS TIME AROUND? ==

Kernel#force has been renamed to Kernel#demand, though Kernel#force  
still exists as an alias. I’m still wavering on the final name.  
Feedback is welcomed.

I’ve also incorporated a very nice suggestion from Tom P., so that  
Object#inspect no longer forces the evaluation of a promise. This makes  
promises much easier to work with in irb.

The biggest new feature is an API for lazy streams. Lazy streams are  
linked lists of deferred computations. Iterating over the list forces  
its evaluation, cell by cell. They can be used for many purposes,  
including a substitute for generators or threads.

As linked lists, each cell in the stream (Lazy::Cons) has two  
attributes: first, and rest. first is the value in that cell, and rest  
is a reference to the tail (remainder) of the list.

There is also a Lazy::Stream class, which wraps a lazy stream and  
implements Enumerable.

The API tries to make both imperative and “pure” stream creation easy.

For example:

# create a stream of lines from stdin

stdin\_lines = Lazy::generate\_stream do |tail|  
line = $stdin.gets  
if line  
[line, tail]  
else  
nil  
end  
end

# create a stream of Fibbonacci numbers

def make\_fibs( a=1, b=0 )  
Lazy::cons\_stream do  
sum = a + b  
[sum, make\_fibs( b, sum )]  
end  
end  
fibs = make\_fibs

You can use them directly, as linked lists:

# echo lines from stdin

iter = stdin\_lines  
while demand( iter )  
puts iter.first  
iter = iter.rest  
end

…or via the Enumerable interface:

# print the Fibbonacci numbers up through 100

enum = Lazy::Stream.new( fibs )  
enum.each do |n|  
puts n  
break if n \> 100  
end

The lazy streams API is still experimental and missing some important  
functionality (take and drop, for example), but it’s already useful at  
this point and I’d like to get some feedback.

== WHERE CAN I GET IT? ==

I’ve got a small web site here:

[http://moonbase.rydia.net/software/lazy.rb/](http://moonbase.rydia.net/software/lazy.rb/)

lazy.rb is available for download as both a tarball and a gem. This is  
my first real gem, so let me know if you have any problems with it.

There’s also a link to the API documentation, but sadly nothing in the  
way of a tutorial yet.

I’ll eventually also start publishing my git repository. I keep meaning  
to get around to it…

-mental

---

<div class="post-metadata">

**Author:** ![mental](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/c77e96/32.png) [@mental](https://www.ruby-forum.com/u/mental)\
**Post date:** [December 11, 2005, 9:04am UTC](https://www.ruby-forum.com/t/lazy-rb-0-2/97140/2 "2005-12-11T09:04:18Z")

</div>

On Dec 10, 2005, at 9:48 PM, MenTaLguY wrote:

> Now that I’m done asking stupid questions about iterators, it’s  
> time for  
> another release of lazy.rb!
> 
> -mental

Mental-

```
This is very interesting stuff! Thanks you for your work on it.

```

Cheers-

-Ezra Z.  
WebMaster  
Yakima Herald-Republic Newspaper  
removed\_email\_address@domain.invalid  
509-577-7732
