Forum: Ruby lazy.rb 0.9.5 -- transparent futures!

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-19 02:09
(Received via mailing list)
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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-19 23:08
(Received via mailing list)
On Feb 18, 2006, at 7:07 PM, MenTaLguY wrote:

>  # 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.

Wow, that is just super studly!

> == What happened to lazy streams from 0.2?
>
> I ditched the lazy streams API for now.  It just wasn't working out.

Can you expand on what you mean by this?  I'm working on a huge
article about infinite streams for my blog and lazy.rb 0.2 was a big
inspiration to me.

James Edward Gray II
Fe57662c550fb3cce44c398ddf2dd706?d=identicon&s=25 unknown (Guest)
on 2006-02-19 23:20
(Received via mailing list)
MenTaLguY wrote:

> I'd like to announce a new version of lazy.rb -- this one offering
> thread safety and transparent futures!

Nice.

>  # forces evaluation
>  p x * 3 # => 24

What will it do for:
  p 3 * x

Thanks for sharing.
3f591bcf8b0c5335f9acc85b6e83481b?d=identicon&s=25 matt.smillie@gmail.com (Guest)
on 2006-02-20 00:24
(Received via mailing list)
If you suspected "the right thing" you'd probably be right:

irb(main):001:0> require 'lazy'
irb(main):002:0> x = promise { 5 + 3 }
=> #<Lazy::Promise computation=#<Proc:0x0035788c@(irb):2>>
irb(main):003:0> p 3 * x
24
=> nil
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 unknown (Guest)
on 2006-02-20 03:44
(Received via mailing list)
Quoting "matt.smillie@gmail.com" <matt.smillie@gmail.com>:

> If you suspected "the right thing" you'd probably be right:
>
> irb(main):001:0> require 'lazy'
> irb(main):002:0> x = promise { 5 + 3 }
> => #<Lazy::Promise computation=#<Proc:0x0035788c@(irb):2>>
> irb(main):003:0> p 3 * x
> 24
> => nil

It's worth noting that this only works so well because of the very
nice coercion machinery Ruby has built around its numeric classes.

Ruby's NUM2INT (for example) will call .to_int on the promise when
FIXNUM_P fails, so everything Just Works(tm).

For other cases (e.g. promises returning file handles), you may find
you need to unwrap them explicitly with demand() to pass them to
certain methods.

Of course this is an issue only when passing promises to methods
implemented in C; lazy.rb does a very good job of faking out Ruby
otherwise (the boolean issue notwithstanding).

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 unknown (Guest)
on 2006-02-20 18:45
(Received via mailing list)
Quoting James Edward Gray II <james@grayproductions.net>:

> > I ditched the lazy streams API for now.  It just wasn't working
> > out.
>
> Can you expand on what you mean by this?  I'm working on a huge
> article about infinite streams for my blog and lazy.rb 0.2 was a
> big inspiration to me.

Oh, mainly it was an aesthetic thing.  It _worked_ fine.

I'd been fighting with the streams API to make it more Ruby-esque
and easier to use properly, but I finally punted on it to get this
release out the door quickly.

In retrospect, I probably should have just kept the 0.2 API for now.
 I definitely want something better for 1.0, though.

-mental
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-21 08:00
(Received via mailing list)
Hah!  Awesome mental, I was going to be implementing something like
this for an Actor library that I'm going to start work on Real Soon
(tm).  And, of course, you did it way better than I would have.

One question: How hard would it be to modify the way that exceptions
are handled to hold off raising the exception until the result was
requested?  I'm thinking specifically of some non-deterministic
situations where you may request a value but never end up needing to
use it.
5c841628b56df3a68984986e9f095d01?d=identicon&s=25 Andrew Johnson (andrew)
on 2006-02-21 09:34
(Received via mailing list)
On Sun, 19 Feb 2006 10:07:12 +0900, MenTaLguY <mental@rydia.net> wrote:
>  http://moonbase.rydia.net/software/lazy.rb/
>
> Bug reports would be very, very welcome.


When I toyed with a proof-of-concept of Io's asynchronous messages in
Ruby

  http://www.siaris.net/index.cgi/Programming/Langua...

Jim Weirich pointed out that methods later added to Object or Kernel
will
no longer be "missing" in the Async (or Future) class. One work around
is
to trap "method_added" up the chain, for example:

  http://www.siaris.net/cgi-bin/siwiki.pl?FeedBack/A...

But then I discovered that methods added by including a module weren't
trapped by method_added -- so in the end, a KernellessObject (from
evil.rb)
was needed (same link as above) as Async's parent to keep the proxy
clean.

regards,
andrew
47b36de21d7ecbc824c81d24802a6290?d=identicon&s=25 Minkoo Seo (pool007)
on 2006-02-21 12:00
(Received via mailing list)
Sorry for newbie question. I tried to install lazy only to fail:

[root@poseidon tmp]# ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]
[root@poseidon tmp]# ls -l lazy-0.9.5.gem
-rw-r--r--  1 mkseo users 6656  2ì?? 19 09:31 lazy-0.9.5.gem
[root@poseidon tmp]# gem install lazy-0.9.5.gem
Attempting local installation of 'lazy-0.9.5.gem'
Successfully installed lazy, version 0.9.5
Installing RDoc documentation for lazy-0.9.5...

lazy.rb:60:22: Couldn't find DIVERGES. Assuming it's a module
[root@poseidon tmp]#

Any idea?

Minkoo Seo
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-21 13:39
Minkoo Seo wrote:
> Sorry for newbie question. I tried to install lazy only to fail:
>
> [root@poseidon tmp]# ruby -v
> ruby 1.8.4 (2005-12-24) [i686-linux]
> [root@poseidon tmp]# ls -l lazy-0.9.5.gem
> -rw-r--r--  1 mkseo users 6656  2ì?? 19 09:31 lazy-0.9.5.gem
> [root@poseidon tmp]# gem install lazy-0.9.5.gem
> Attempting local installation of 'lazy-0.9.5.gem'
> Successfully installed lazy, version 0.9.5
  ^^^^^^^^^^^^

The installatiof of the lazy software is OK ...

> Installing RDoc documentation for lazy-0.9.5...
>
> lazy.rb:60:22: Couldn't find DIVERGES. Assuming it's a module

Its just that RDoc is complaining about something.  I got the same error
on my system, but the RDoc looks ok, even with the error.

--
-- Jim Weirich
47b36de21d7ecbc824c81d24802a6290?d=identicon&s=25 Minkoo Seo (pool007)
on 2006-02-21 17:00
(Received via mailing list)
Still, no luck.

[root@poseidon tmp]# ll
í?©ê³? 12
-rw-r--r--  1 mkseo users 6656  2ì?? 19 09:31 lazy-0.9.5.gem
[root@poseidon tmp]# gem install lazy-0.9.5.gem
Attempting local installation of 'lazy-0.9.5.gem'
Successfully installed lazy, version 0.9.5
Installing RDoc documentation for lazy-0.9.5...

lazy.rb:60:22: Couldn't find DIVERGES. Assuming it's a module
[root@poseidon tmp]# irb
irb(main):001:0> require 'lazy'
LoadError: no such file to load -- lazy
        from (irb):1:in `require'
        from (irb):1
irb(main):002:0> require 'lazy/future'
LoadError: no such file to load -- lazy/future
        from (irb):2:in `require'
        from (irb):2
irb(main):003:0>

[root@poseidon tmp]# ls -l /usr/local/lib/ruby/gems/1.8/gems/
í?©ê³? 72
drwxr-xr-x   4 root root 4096  2ì?? 12 07:32 actionmailer-1.1.5/
drwxr-xr-x   5 root root 4096  2ì?? 12 07:32 actionpack-1.11.2/
drwxr-xr-x   5 root root 4096  2ì?? 12 07:32 actionwebservice-1.0.0/
drwxr-xr-x   5 root root 4096  2ì?? 12 07:31 activerecord-1.13.2/
drwxr-xr-x   3 root root 4096  2ì?? 12 07:31 activesupport-1.2.5/
drwxr-xr-x   3 root root 4096  2ì?? 22 00:42 lazy-0.9.5/
drwxr-xr-x  11 root root 4096  2ì?? 12 07:32 rails-1.0.0/
drwxr-xr-x   6 root root 4096  2ì?? 12 07:31 rake-0.7.0/
drwxr-xr-x   3 root root 4096  2ì?? 12 07:30 sources-0.0.1/


[root@poseidon tmp]# ls -l /usr/local/lib/ruby/1.8/ | grep lazy
[root@poseidon tmp]#

I've taken the liberty of posting installation problem to this post,
because this is the first time for me to install local *.gem file.
Can anybody tell me why this is happening? Isn't the lazy.rb file
supposed to be installed in /usr/local/lib/ruby/1.8 ?

- Minkoo Seo
A9b6a93b860020caf9d2d1d58c32478f?d=identicon&s=25 Ross Bamford (Guest)
on 2006-02-21 17:25
(Received via mailing list)
On Wed, 2006-02-22 at 00:58 +0900, Minkoo Seo wrote:
> lazy.rb:60:22: Couldn't find DIVERGES. Assuming it's a module
> [root@poseidon tmp]# irb
> irb(main):001:0> require 'lazy'
> LoadError: no such file to load -- lazy
>         from (irb):1:in `require'
>         from (irb):1
> irb(main):002:0> require 'lazy/future'
> LoadError: no such file to load -- lazy/future
>         from (irb):2:in `require'
>         from (irb):2
> irb(main):003:0>

Haven't followed this thread all the way, but I'm assuming you must have
already tried:

	$ irb
	require 'rubygems'
	require 'lazy'

Or alternatively passing -rubygems as an option to IRB.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-02-21 17:59
(Received via mailing list)
On Feb 21, 2006, at 10:58 AM, Minkoo Seo wrote:

> lazy.rb:60:22: Couldn't find DIVERGES. Assuming it's a module
>
> drwxr-xr-x   3 root root 4096  2ì?? 12 07:30 sources-0.0.1/
> - Minkoo Seo
>
>

require 'rubygems'
require 'lazy'
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-21 19:28
(Received via mailing list)
On Tue, 2006-02-21 at 16:00 +0900, Daniel Nugent wrote:
> One question: How hard would it be to modify the way that exceptions
> are handled to hold off raising the exception until the result was
> requested?  I'm thinking specifically of some non-deterministic
> situations where you may request a value but never end up needing to
> use it.

Hmm, if it doesn't already do that, it's a bug.

Can you give me a test case which demonstrates the problem?

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-21 19:31
(Received via mailing list)
On Tue, 2006-02-21 at 17:33 +0900, Andrew Johnson wrote:

> But then I discovered that methods added by including a module weren't
> trapped by method_added -- so in the end, a KernellessObject (from evil.rb)
> was needed (same link as above) as Async's parent to keep the proxy clean.

Hmm, good catch.  Thanks!

I wonder if it's worth introducing a dependency on evil.rb?

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-21 19:34
(Received via mailing list)
On Tue, 2006-02-21 at 21:39 +0900, Jim Weirich wrote:
> Its just that RDoc is complaining about something.  I got the same error
> on my system, but the RDoc looks ok, even with the error.

DIVERGES is a nodoc'd constant which is used internally.  If anyone can
find a way to avoid the RDoc warning, I'd really appreciate it...

-mental
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-21 19:37
(Received via mailing list)
On Feb 21, 2006, at 12:29 PM, MenTaLguY wrote:

>> no longer be "missing" in the Async (or Future) class. One work
>> proxy clean.
>
> Hmm, good catch.  Thanks!
>
> I wonder if it's worth introducing a dependency on evil.rb?

Oh, I don't think so.  It would cut off some users, like me.  ;)

James Edward Gray II
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-21 20:01
(Received via mailing list)
I must've misread the code (or misunderstood something)....

Yep.  Thought the rescue clause raised the exception out of the thread
instead of just storing it.

In that case, what I want (I'm so damn greedy :D) is to be able to
raise the exception immediately (in a case where you damned well know
that you're going to need the value and would prefer to fail early)
and I see that that's trivial to implement (just have a conditional
toss the exception up in the thread if some @raise_immediately flag is
set to true).

There's one other thing I was wondering about: What's the prudency of
adding a method to Future to allow the Future to go back to sleep
(release the lock, pass the thread)?  In this case, I'm considering
waiting for a resource that some other future/thread might be using,
or waiting for a port to get some data. (mostly implementation details
for that library I mentioned, I'll deal with them, but I'm curious if
there's any issue I'm forgetting).
5c841628b56df3a68984986e9f095d01?d=identicon&s=25 Andrew Johnson (andrew)
on 2006-02-21 20:29
(Received via mailing list)
On Wed, 22 Feb 2006 03:35:03 +0900, James Edward Gray II
<james@grayproductions.net> wrote:
> On Feb 21, 2006, at 12:29 PM, MenTaLguY wrote:
>>
>> I wonder if it's worth introducing a dependency on evil.rb?
>
> Oh, I don't think so.  It would cut off some users, like me.  ;)

At one point I was going to try to extract a minimum subset of evil
to just allow for KernellessObject, but never got to it. Would such
a small_evil.rb be less of a dependency concern?

andrew
Fe9b2d0628c0943af374b2fe5b320a82?d=identicon&s=25 Eero Saynatkari (rue)
on 2006-02-21 21:16
MenTaLguY wrote:
> On Tue, 2006-02-21 at 21:39 +0900, Jim Weirich wrote:
>> Its just that RDoc is complaining about something.  I got the same error
>> on my system, but the RDoc looks ok, even with the error.
>
> DIVERGES is a nodoc'd constant which is used internally.  If anyone can
> find a way to avoid the RDoc warning, I'd really appreciate it...

Did you try   # :nodoc:  ?

> -mental


E
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-21 22:48
MenTaLguY wrote:
> On Tue, 2006-02-21 at 17:33 +0900, Andrew Johnson wrote:
>
>> But then I discovered that methods added by including a module weren't
>> trapped by method_added -- so in the end, a KernellessObject (from evil.rb)
>> was needed (same link as above) as Async's parent to keep the proxy clean.
>
> Hmm, good catch.  Thanks!
>
> I wonder if it's worth introducing a dependency on evil.rb?

The BlankSlate class in Builder handles this without resorting to the
"evil" that lies in the heart of evil.rb.  And the CVS head version of
BlankSlate also handles the module hole Andrew mentioned earlier (I
think ... I just now updated it).4

--
-- Jim Weirich
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-21 23:34
(Received via mailing list)
On Wed, 2006-02-22 at 06:49 +0900, Jim Weirich wrote:
> MenTaLguY wrote:
> The BlankSlate class in Builder handles this without resorting to the
> "evil" that lies in the heart of evil.rb.  And the CVS head version of
> BlankSlate also handles the module hole Andrew mentioned earlier (I
> think ... I just now updated it).4

Hmm, that sounds more like it.  Any chance of a separate BlankSlate gem?

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-21 23:53
(Received via mailing list)
On Wed, 2006-02-22 at 04:01 +0900, Daniel Nugent wrote:
> In that case, what I want (I'm so damn greedy :D) is to be able to
> raise the exception immediately (in a case where you damned well know
> that you're going to need the value and would prefer to fail early)
> and I see that that's trivial to implement (just have a conditional
> toss the exception up in the thread if some @raise_immediately flag is
> set to true).

> There's one other thing I was wondering about: What's the prudency of
> adding a method to Future to allow the Future to go back to sleep
> (release the lock, pass the thread)?  In this case, I'm considering
> waiting for a resource that some other future/thread might be using,
> or waiting for a port to get some data. (mostly implementation details
> for that library I mentioned, I'll deal with them, but I'm curious if
> there's any issue I'm forgetting).

Hmm.  Could you give me some examples of the behavior you have in mind?

-mental
5c841628b56df3a68984986e9f095d01?d=identicon&s=25 Andrew Johnson (andrew)
on 2006-02-21 23:56
(Received via mailing list)
On Wed, 22 Feb 2006 06:49:11 +0900, Jim Weirich <jim@weirichhouse.org>
wrote:
> MenTaLguY wrote:
[snip]
>> I wonder if it's worth introducing a dependency on evil.rb?
>
> The BlankSlate class in Builder handles this without resorting to the
> "evil" that lies in the heart of evil.rb.  And the CVS head version of
> BlankSlate also handles the module hole Andrew mentioned earlier (I
> think ... I just now updated it).4

That does appear to plug it -- and I even recall looking at
append_features back then and not seeing it. Thanks Jim!

andrew
32edd0717b3144d5c58a352d613abdc9?d=identicon&s=25 gabriele renzi (Guest)
on 2006-02-21 23:56
(Received via mailing list)
James Edward Gray II ha scritto:

>> Hmm, good catch.  Thanks!
>>
>> I wonder if it's worth introducing a dependency on evil.rb?

maybe just making it optional.. you could even make great use of
Object#become :)
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-22 01:09
(Received via mailing list)
Actually, now I'm not so sure that I read that part either....

What's the purpouse of the spinlock in __synchronize__?

To keep a Future's block from evaluating several times in parallel?

I think I thought it was to keep several futures from evaluating at
the same time.
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-22 01:36
(Received via mailing list)
On Wed, 2006-02-22 at 09:07 +0900, Daniel Nugent wrote:
> What's the purpouse of the spinlock in __synchronize__?

> To keep a Future's block from evaluating several times in parallel?

s/Future/Promise/, and you've got it.

It ensures that each promise only ever gets evaluated once, even when
multiple threads demand its result at the same time.

Nothing to do with futures in particular; I only require threadsafe for
futures because using futures guarantees that your program will have
multiple threads.

-mental
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-22 02:16
(Received via mailing list)
Right, then there's no purpouse to being able to put the lock down.  I
think I thought that the lock was class level instead of instance
level.

BTW: Could you point me in the direction of some circular programming
examples?  It sounds like an interesting technique, but the papers on
the net all seem to be in post script and I don't care to futz with
GhostWriter again.
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-22 03:55
MenTaLguY wrote:
> On Wed, 2006-02-22 at 06:49 +0900, Jim Weirich wrote:
>> MenTaLguY wrote:
>> The BlankSlate class in Builder handles this without resorting to the
>> "evil" that lies in the heart of evil.rb.  And the CVS head version of
>> BlankSlate also handles the module hole Andrew mentioned earlier (I
>> think ... I just now updated it).4
>
> Hmm, that sounds more like it.  Any chance of a separate BlankSlate gem?

Ask and ye shall receive:

   gem install blankslate --source http://onestepback.org/betagems

This is a quick breakout of the BlankSlate class into its own gem.  It
now sits as a top level namespace (instead of being nested in the
Builder module).  It is built from the same source as Builder, so the
builder gem still includes the class physically.  (Shouldn't be a
problem unless there start to be weird version mismatches).

There are still some documentation issues (e.g. the blankslate gem RDoc
still refers to the builder README file), but give this guy a spin
around the block before I make an official release.

--
-- Jim Weirich
D8831c4665a164c6ce484003deb1afd6?d=identicon&s=25 Guillaume Marcais (Guest)
on 2006-02-22 04:13
(Received via mailing list)
Le 21 févr. 06, à 21:55, Jim Weirich a écrit :

> gem install blankslate --source http://onestepback.org/betagems

irb(main):004:0> require 'blankslate'
LoadError: No such file to load -- builder
         from
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in
`require__'
         from
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require'
         from /usr/lib/ruby/site_ruby/1.8/rubygems.rb:163:in `activate'
         from
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:23:in `require'
         from (irb):4

Seems that the dependency on builder is still there.

Guillaume.
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-22 07:27
Guillaume Marcais wrote:
> Le 21 f�vr. 06, � 21:55, Jim Weirich a �crit :
>
>> gem install blankslate --source http://onestepback.org/betagems
>
> irb(main):004:0> require 'blankslate'
> LoadError: No such file to load -- builder

Dang!  Autorequire bit me again.

Ok, I think I fixed it.  Give it another try.

--
-- Jim Weirich
2ea2840648beec7d5510cdeebd3a9a66?d=identicon&s=25 Shashank Date (Guest)
on 2006-02-22 23:17
(Received via mailing list)
Hi,

  I have a feature request (along with a quick-hack solution).

  Please ignore if this is already done or sounds crazy. :-)

  Problem: All the promises I make, cannot have any arguments ! !

  So something like this is what I have in mind:

  x = promise("CUSTOMERS") { |table_name|
long_running_query(table_name)}

  Admitedly, in this one-liner it does not make much sense. But if the
block had many many lines of code and referred to the block variable at
multiple places, suddenly it would be mean more to me.

  I have attached my hackish solution without really thinking all the
way thru.
  Thanks,

  -- Shashank


MenTaLguY <mental@rydia.net> wrote:
  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.
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-23 00:52
(Received via mailing list)
On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:

> Ok, I think I fixed it.  Give it another try.

ERROR:  While executing gem ... (YAML::Error)
    Invalid object explicitly tagged !ruby/Object: "requir"

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-23 01:04
(Received via mailing list)
On Wed, 2006-02-22 at 14:14 -0800, Shashank Date wrote:
> Problem: All the promises I make, cannot have any arguments ! !

> So something like this is what I have in mind:
>
> x = promise("CUSTOMERS") { |table_name|
>  long_running_query(table_name)}

Hmm.  Would this work?

 table_name = "CUSTOMERS"
 x = promise { long_running_query(table_name) }

-mental
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-23 14:16
MenTaLguY wrote:
> On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:
>
>> Ok, I think I fixed it.  Give it another try.
>
> ERROR:  While executing gem ... (YAML::Error)
>     Invalid object explicitly tagged !ruby/Object: "requir"

Ahhh ... Interesting.

I've tracked this down to a corrupt compressed gem index on my beta
server.  My home box wasn't getting it because it uses a unreleased
version of RubyGems that does incremental downloads of the individual
gem specs rather than grabbing the massive gem index all the time.

This might also explain an unrelated issue I was having with testing
RubyGems.  I think this bug has made my day.

Now all I have to do is fix it.

Thanks.

--
-- Jim Weirich
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-24 02:13
Jim Weirich wrote:
> MenTaLguY wrote:
>> On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:
>>
>>> Ok, I think I fixed it.  Give it another try.
>>
>> ERROR:  While executing gem ... (YAML::Error)
>>     Invalid object explicitly tagged !ruby/Object: "requir"
>
> Ahhh ... Interesting.
>
> I've tracked this down to a corrupt compressed gem index on my beta
> server.  My home box wasn't getting it because it uses a unreleased
> version of RubyGems that does incremental downloads of the individual
> gem specs rather than grabbing the massive gem index all the time.
>
> This might also explain an unrelated issue I was having with testing
> RubyGems.  I think this bug has made my day.
>
> Now all I have to do is fix it.

Yep, it was a bug in the new RubyGems server-side indexing software.
Should be fixed now.  Give it another try...

   gem install blankslate -s http://onestepback.org/betagems

--
-- Jim Weirich
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-24 05:32
(Received via mailing list)
Mental, could I perchance persuade you to add an optional parameter to
the Future initializer that accepts a block to be run inside the
rescue clause of the Future's thread?

The situation I am specifically thinking of is this:

I have a number of objects that will want the value resulting from the
Future.  I know all of these objects WILL need to access that value.
Because the computation in the Future is very expensive, I would like
to raise exceptions on those objects as soon as the thread is caught
so that they can begin handling the error as soon as possible.

So, at the time of the exception, I can lock down the current
subscribers list and then fire off the exception to each of them.
Something like this:

future(lambda{|exception| lock.synchronize{subscribers.each{|s|
s.raise(exception)}}}){holy_crap_long_execution}
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 unknown (Guest)
on 2006-02-24 19:23
(Received via mailing list)
Quoting Daniel Nugent <nugend@gmail.com>:

> Mental, could I perchance persuade you to add an optional
> parameter to
> the Future initializer that accepts a block to be run inside the
> rescue clause of the Future's thread?
>
> future(lambda{|exception| lock.synchronize{subscribers.each{|s|
> s.raise(exception)}}}){holy_crap_long_execution}

How about:

 future {
   begin
     holy_crap_long_execution
   rescue Exception => exception
     lock.synchronize do
       subscribers.each { |s| s.raise( exception ) }
     end
     raise
   end
 }

?

That might be a bit longer, but it seems clearer what's going on.

-mental
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 MenTaLguY (Guest)
on 2006-02-26 00:18
(Received via mailing list)
On Fri, 2006-02-24 at 10:13 +0900, Jim Weirich wrote:
> Yep, it was a bug in the new RubyGems server-side indexing software.
> Should be fixed now.  Give it another try...
>
>    gem install blankslate -s http://onestepback.org/betagems

Hmm.  Okay, for lazy.rb there are a couple things I would need from
BlankSlate:

 - the ability to "let through" a few additional methods
   (just Object#class at the moment, but there may be more later)

 - to be able to hide Object#instance_eval

Maybe the best thing would be a factory that creates customized
BlankSlate-like classes, roughly similar to the way Struct works.

Thoughts?

-mental
70c8da82d09d3866222976ab8978133c?d=identicon&s=25 Daniel Nugent (Guest)
on 2006-02-26 05:34
(Received via mailing list)
Good idea, thanks!
Ab870531383eea6e4d9110317f5401e7?d=identicon&s=25 Caleb Clausen (Guest)
on 2006-02-26 07:06
(Received via mailing list)
On 2/25/06, MenTaLguY <mental@rydia.net> wrote:
> Hmm.  Okay, for lazy.rb there are a couple things I would need from
> BlankSlate:
>
>  - the ability to "let through" a few additional methods
>    (just Object#class at the moment, but there may be more later)
>
>  - to be able to hide Object#instance_eval

I have a rather mutated version of BlankSlate (as a module) which
supports both of these.
You can use it something like this:

class Foo
  include BlankSlate
  hide :instance_eval
  restore :class
end

Foo.new.instance_eval{}  #=> raises NoMethodError
Foo.new.class                #=> Foo

Is there any chance these features could be included in the gem? I'd
love to use it myself, but I need my various changes to it too.

Here's the code:


  module BlankSlate
    module ClassMethods
      def restore(*names)
        names.each{|name| alias_method name, "##{name}"}
      end
      def hide(*names)
        names.each do|name|
          undef_method name  if instance_methods.include?(name.to_s)
        end
      end
    end

    def BlankSlate.included(othermod)
      othermod.instance_eval {
        instance_methods.each { |m|
          #nothing is thrown away forever, just renamed in a strange way
          alias_method "##{m}", m #archive m
          undef_method m unless m =~ /^__/ || m=='instance_eval'
        }
        extend BlankSlate::ClassMethods
      }
    end
  end
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-02-26 13:10
MenTaLguY wrote:
> On Fri, 2006-02-24 at 10:13 +0900, Jim Weirich wrote:
>> Yep, it was a bug in the new RubyGems server-side indexing software.
>> Should be fixed now.  Give it another try...
>>
>>    gem install blankslate -s http://onestepback.org/betagems
>
> Hmm.  Okay, for lazy.rb there are a couple things I would need from
> BlankSlate:
>
>  - the ability to "let through" a few additional methods
>    (just Object#class at the moment, but there may be more later)
>
>  - to be able to hide Object#instance_eval
>
> Maybe the best thing would be a factory that creates customized
> BlankSlate-like classes, roughly similar to the way Struct works.

Instance_eval can be hidden with a call to hide.  This class method is
trivial to reimplement, although the general case might need something
like Caleb suggested.

  class BS < BlankSlate
    hide :instance_eval
    def class
      BS
    end
  end

--
-- Jim Weirich
47b36de21d7ecbc824c81d24802a6290?d=identicon&s=25 Minkoo Seo (pool007)
on 2006-02-26 17:14
(Received via mailing list)
Hi mental. Thank you for the really nice library.

I'm sorry if this bothers you, but I have no idea what "circular
programming" is. Could you give me an example? Especially, what does
"matryoshka = demand( promise { |result| [result] } )" mean?

I also suggest that you should upload the description posted here to
your own website(http://moonbase.rydia.net/software/lazy.rb/), so that
people can find out what lazy.rb really is. IMHO, RDoc itself is not
sufficient.

- Minkoo Seo
This topic is locked and can not be replied to.