[ANN] lazy.rb

M

MenTaLguY

--=-kNANzcWuDUq7R1tLazWl
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

I've got an 0.0 release of lazy.rb, an implementation of lazy evaluation
for Ruby, up here:

http://moonbase.rydia.net/software/lazy/

It provides two functions: promise (like R5 Scheme's delay) and force
(just as in Scheme).

promise takes a block to evaluate later; as an aid to circular
programming, the block's result is passed to it as a parameter.

force is used to force the value of a promised computation.

Some attempts have been made to support implicit forcing through the use
of SimpleDelegator, but with only mixed success so far.

-mental

--=-kNANzcWuDUq7R1tLazWl
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDarXpcUNIGiXCc4MRAiHLAJsGAh+cVLpJTg086/L7zltNCHt5SACeJY7r
X8jUZK0M3aOeUYe9tBe2Jp0=
=6IYm
-----END PGP SIGNATURE-----

--=-kNANzcWuDUq7R1tLazWl--
 
P

Pit Capitain

MenTaLguY said:
I've got an 0.0 release of lazy.rb, an implementation of lazy evaluation
for Ruby, up here:

http://moonbase.rydia.net/software/lazy/

It provides two functions: promise (like R5 Scheme's delay) and force
(just as in Scheme).

promise takes a block to evaluate later; as an aid to circular
programming, the block's result is passed to it as a parameter.

force is used to force the value of a promised computation.

Some attempts have been made to support implicit forcing through the use
of SimpleDelegator, but with only mixed success so far.

Hi mental,

do you have some unit tests or an example where implicit forcing isn't
working as you'd like?

Regards,
Pit
 
M

MenTaLguY

--=-MIR4BzBPMjYxad4/vjsX
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Hi mental,
=20
do you have some unit tests or an example where implicit forcing isn't=20
working as you'd like?

Err... unit tests. Those would be nice.

But, here are a couple examples:

blah =3D promise { 3 }
p blah.methods.include? "+" # =3D> false, failed to force
force( blah )
p blah.methods.include? "+" # =3D> true

...and:

foo =3D promise { 3 }
begin
p [][foo] # TypeError: can't convert Lazy::Thunk into Integer
rescue TypeError =3D> e
puts e
end
force( foo )
p [][foo] # =3D> nil

Same problem in both cases, basically.

Oh, and if you try these in irb, remember that you will get different
results because irb's attempt to display the result value will force the
promise.

-mental

--=-MIR4BzBPMjYxad4/vjsX
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDa1mccUNIGiXCc4MRAnLjAKCPySixdpXlOlftu3can8gatLhe6wCeIw9N
gqZn/M6asBM8YCeFBJl0ZaM=
=IyHW
-----END PGP SIGNATURE-----

--=-MIR4BzBPMjYxad4/vjsX--
 
P

Pit Capitain

MenTaLguY said:
...
Same problem in both cases, basically.

Here's another implementation that doesn't have these problems:

module Lazy #:nodoc: all
class Thunk
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
def initialize( &computation )
@computation = computation
end
def method_missing( *args, &block )
( @result ||= @computation.call( self ) ).send( *args, &block )
end
end
end

Regards,
Pit
 
T

Trans

Pit said:
Here's another implementation that doesn't have these problems:

module Lazy #:nodoc: all
class Thunk
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
def initialize( &computation )
@computation = computation
end
def method_missing( *args, &block )
( @result ||= @computation.call( self ) ).send( *args, &block )
end
end
end

Ah, that clarifies things. This is essentially a pass-thru Functor with
a cached result. (Why is 'self' being passed to the computation
though?) While not quite the same as the implict lambda's I suggested,
it is interesting just how similar they are.

This whole Functor paradigm, including things like #every, #enum_for,
#as (was #superfunc), etc. and now this --all are various simple
decorators of a special form where the heart of code is some sort of
transfomation in method_missing. Insteresting stuff. It would be even
more interesting to see if this could somehow be embodied in core so to
operate more efficiently (and perhaps a syntax variation on the
methods?) --this techinque may have potential for roles and namespace
selectors too.

T.
 
M

MenTaLguY

--=-NggxC2Ek7RSFnT5oSDMT
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

(Why is 'self' being passed to the computation though?)

For convenience in circular programming; it's an easier way for the
computation to get access to its own future result.

Rather than having to do:

result =3D nil
result =3D promise {
... do something with result ...
}

It allows simply:

promise { |result|
... do something with result ...
}

-mental

--=-NggxC2Ek7RSFnT5oSDMT
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDbN05cUNIGiXCc4MRArwkAKDAwqNbbvTCLQRQ3HeIexDTY0So7ACgg2eo
RNHfdSoew4IT3eQBzmX4yYE=
=WVou
-----END PGP SIGNATURE-----

--=-NggxC2Ek7RSFnT5oSDMT--
 
M

MenTaLguY

--=-ZlhVJ8JMal4ZXqCk8y/T
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

=20
Here's another implementation that doesn't have these problems:
=20
module Lazy #:nodoc: all
class Thunk
instance_methods.each { |m| undef_method m unless m =3D~ /^__/ }
def initialize( &computation )
@computation =3D computation
end
def method_missing( *args, &block )
( @result ||=3D @computation.call( self ) ).send( *args, &block = )
end
end
end

Hmm, I can adapt this, I think. Thanks. It does have a few problems as
written; e.g.:

1. since @computation isn't set to nil after being run, the closure
can't get garbage collected until the thunk is

2. the computation will get run multiple times if its result is nil
or false

3. There's no way to unwrap the value from the thunk

But I think you got me over the hump. Look for another lazy.rb release
soonish.

-mental

--=-ZlhVJ8JMal4ZXqCk8y/T
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDbOiDcUNIGiXCc4MRAucwAJ9lASHEbQdcR/HyHQK2cRyErlKNaACgnCOv
nCqM5fXZu36bNdeIy/bq8wk=
=Do0h
-----END PGP SIGNATURE-----

--=-ZlhVJ8JMal4ZXqCk8y/T--
 
D

Devin Mullins

MenTaLguY said:
2. the computation will get run multiple times if its result is nil
or false
Use defined?
3. There's no way to unwrap the value from the thunk
What's in a value? That which we call a String by any other class would
#to_s as neat.

Devin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,701
Latest member
XavierQ83

Latest Threads

Top