[ANN] lazy.rb 0.9.5 -- transparent futures!

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

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

-mental

···

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.

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

···

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. :wink:

--
Andrew L. Johnson http://www.siaris.net/
      Doing linear scans over an associative array is like
      trying to club someone to death with a loaded Uzi.
          -- Larry Wall

MenTaLguY 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

···

On Tue, 2006-02-21 at 21:39 +0900, Jim Weirich wrote:

--
Posted via http://www.ruby-forum.com/\.

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

-mental

···

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

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

···

On Wed, 22 Feb 2006 06:49:11 +0900, Jim Weirich <jim@weirichhouse.org> wrote:

--
Andrew L. Johnson http://www.siaris.net/
      It's kinda hard trying to remember Perl syntax *and* Occam's
      razor at the same time :slight_smile:
          -- Graham Patterson

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 :slight_smile:

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

···

On 2/21/06, MenTaLguY <mental@rydia.net> wrote:

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

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

iD8DBQBD+1uMSuZBmZzm14ERAj4HAKDRRv4oplZVejcfLDJ6k7x8Ovcl+wCgiSbz
G6QQwTFxw+EQTR3g9/oGjJ8=
=vqXa
-----END PGP SIGNATURE-----

--
-Dan Nugent

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

···

On Wed, 2006-02-22 at 06:49 +0900, Jim Weirich wrote:

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

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

-mental

···

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

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.

···

Le 21 févr. 06, à 21:55, Jim Weirich a écrit :

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

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.

···

On 2/21/06, MenTaLguY <mental@rydia.net> wrote:

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

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

iD8DBQBD+5mBSuZBmZzm14ERAhOzAKCLGB4FlLX4gGrymjU51xnmdPUF+wCg22Uj
6mbmd42ukUab11RpK8WZ3Q4=
=oQMk
-----END PGP SIGNATURE-----

--
-Dan Nugent

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

--
Posted via http://www.ruby-forum.com/\.

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

···

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?

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

-mental

···

On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:

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

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.

···

On 2/21/06, MenTaLguY <mental@rydia.net> wrote:

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

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

iD8DBQBD+7GqSuZBmZzm14ERAr9RAKDaPWxo4bWt1VQTslG7rh6cOa+glgCdHmZZ
3luo9rohBNy0c0WnC5Dp+v4=
=R/te
-----END PGP SIGNATURE-----

--
-Dan Nugent

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

···

On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

Jim Weirich wrote:

MenTaLguY 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

···

On Wed, 2006-02-22 at 15:27 +0900, Jim Weirich wrote:

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.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?

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}

···

On 2/23/06, Jim Weirich <jim@weirichhouse.org> wrote:

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

--
Posted via http://www.ruby-forum.com/\.

--
-Dan Nugent

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

···

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

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