I’d like to announce a new version of lazy.rb – this one offering
thread safety and transparent futures!
Here’s the web site, complete with gem and tarball downloads, plus a bit
of documentation:
http://moonbase.rydia.net/software/lazy.rb/
Bug reports would be very, very welcome.
== What is lazy.rb?
lazy.rb is a library providing transparent lazy evaluation and futures
for Ruby. It provides a bag of clever tricks to help you avoid doing
expensive computations up front.
= Lazy Evaluation
Lazy evaluation simply refers to computations which are run on an
as-needed basis. For example:
x = promise { 3 + 5 }
Means that the block – 3 + 5 – won’t actually be evaluated until
something tries to use x’s value.
p x # => #<Lazy::Promise computation=#Proc:...>
forces evaluation
p x * 3 # => 24
p x # => 8
You can also force evaluation using demand:
x = promise { 3 + 5 }
p x # => #<Lazy::Promise computation=#Proc:...>
forces evaluation
p demand( x ) # => 8
p x # => 8
It’s a bit silly for 3 + 5, but it’s handy for more intensive
calculations. You can unconditionally promise a computation, yet only
pay for it if and when its result is actually used.
= Futures
Futures are blocks of code that are evaluated immediately, but in a
background thread.
x = future { 3 + 5 }
p x # => #<Lazy::Future computation=#Proc:...>
You could do other stuff here while
the computation ran in the background
blocks until the background thread completes
p x * 3 # => 24
p x # => 8
Again, silly for 3 + 5 perhaps, but I’m sure you can see how this might
come in handy for more involved computations.
= Other stuff
lazy.rb also includes support for circular programming, where a
computation is passed its own result:
matryoshka = demand( promise { |result| [result] } )
p matryoshka # => [[…]]
p matryoshka.object_id # => -605506544
p matryoshka.first.object_id # => -605506544
p matryoshka.first.first.object_id # => -605506544
This works for both promises and futures, although it has the usual
limitations: if a computation tries to call methods on its own result,
it will diverge.
== What’s new in 0.9.5?
-
Optional support for multithreaded programs:
require ‘lazy/threadsafe’ and you can safely use lazy evaluation in
multithreaded programs. -
Futures:
With thread support, it turned out that futures were really
easy to implement atop promises – just fire off a thread with the
computation and return a promise to join the thread and grab its
result. So I implemented that.
== What happened to lazy streams from 0.2?
I ditched the lazy streams API for now. It just wasn’t working out.
== What next?
Except perhaps for lazy streams (which might end up becoming a separate
library), I think we’re nearly feature-complete. Ideas and suggestions
are very welcome, though.
-mental