Forum: Ruby Futures in Ruby

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.
Adam S. (Guest)
on 2006-01-09 23:24
(Received via mailing list)
I was looking at the Io documentation, just to see what the language
looked like and saw the asynchronous support, pretty cool.  Then it
sort of dawned on my how Futures worked, no it isn't all that
complicated, but I it's amazing what you can avoid thinking about.  Who
knows, I think looking into the gaze of a new language, and reading too
much of _why's Redhanded is likely to provide random inspiration.  So
here is a quick implementation of transparent futures in ruby.  Two
questions:
1. Is it worth tossing this on RubyForge or some such place?
2. I'd like to use BlankSlate, but it's part of Builder, but it seems
silly for this to depend on all of the Builder gem, so for demo
purposes BlankSlate is pasted in and taken out of the Builder
namespace.

To try it out do something like this:
require 'future'
f = Future.new{sleep 5; 10}  # Returns immediately
f + 1 # 11 after a pause

  .adam



#--
# Copyright 2004 by Jim W. (removed_email_address@domain.invalid).
# All rights reserved.

# Permission is granted for use, copying, modification, distribution,
# and distribution of modified versions of this work as long as the
# above copyright notice is included.
#++

# BlankSlate provides an abstract base class with no predefined
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
# BlankSlate is useful as a base class when writing classes that
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
class BlankSlate #:nodoc:
  class << self
    def hide(name)
     undef_method name if
       instance_methods.include?(name.to_s) and
       name !~ /^(__|instance_eval)/
    end
  end

  instance_methods.each { |m| hide(m) }
end

# Since Ruby is very dynamic, methods added to the ancestors of
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
# list of available BlankSlate methods.  We handle this by defining a
hook in the Object and Kernel classes that will hide any defined
module Kernel #:nodoc:
  class << self
    alias_method :blank_slate_method_added, :method_added
    def method_added(name)
      blank_slate_method_added(name)
      return if self != Kernel
      BlankSlate.hide(name)
    end
  end
end

class Object #:nodoc:
  class << self
    alias_method :blank_slate_method_added, :method_added
    def method_added(name)
      blank_slate_method_added(name)
      return  if self != Object
      BlankSlate.hide(name)
    end
  end
end


# Future
# Adam S. fooling around on 2006-01-07
class Future < BlankSlate
	def initialize(*args, &block)
		@__thread = Thread.new do
			@__value = block.call(*args)
		end
	end

	def __getobj__
		if @__thread
			@__thread.join
			@__thread = nil
		end
		@__value
	end

	def method_missing(sym, *args, &block)
		__getobj__.send sym, *args, &block
	end

	def inspect
		(@__thread) ? "Unevaluated Future on #{@__thread.inspect}" :
@__value.inspect
	end
end
Jacob F. (Guest)
on 2006-01-09 23:37
(Received via mailing list)
On 1/9/06, Adam S. <removed_email_address@domain.invalid> wrote:
> So here is a quick implementation of transparent futures in ruby.

Also see http://jacob.fugal.net/blog/4

There are some significant differences in implementation between mine
and yours, particularly that yours is a mix between futures and
asyncs. If I understand correctly (which I may not), the body of a
future shouldn't be executed until requested. This is important in
that the body of the future may have side effects that shouldn't be
invoked until requested. Thus starting the thread that calculates the
future right away isn't quite correct. But as a mix between futures
and asyncs, I can see how it might be useful.

Jacob F.
Adam S. (Guest)
on 2006-01-10 01:11
(Received via mailing list)
Interesting, I wasn't aware of that difference.  My assumption was that
asynchs in Io were just asynchronous calls that required no result
which is quite likely wrong.  I mostly went off of things I've gleaned
from the Java Concurrency package:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/...

Your implementation appears to be more like mental's Promises
http://www.ruby-forum.com/topic/48121

They're all subtly different, handy constructs :)
  .adam
Trejkaz (Guest)
on 2006-01-10 04:45
(Received via mailing list)
I think the semantics in this case are just semantics.  The difference
between a "future" being executed on request and being executed in the
background is merely the difference between two implementations of the
executor service the task was run under (another implementation might
even calculate the future up-front.)
Jacob F. (Guest)
on 2006-01-10 06:21
(Received via mailing list)
On 1/9/06, Trejkaz <removed_email_address@domain.invalid> wrote:
> I think the semantics in this case are just semantics.  The difference
> between a "future" being executed on request and being executed in the
> background is merely the difference between two implementations of the
> executor service the task was run under (another implementation might
> even calculate the future up-front.)

Not really. As I said, there may be side-effects that shouldn't occur
until the value is actually processed. As far as delayed effects, true
this wouldn't matter as much. But say the future wraps a
mathematically intensive operation that may or may not be used in the
program. I certainly want to put off that operation until I know I
need it. To be clear, I'm not arguing that this interpretation is more
correct -- an implementation that calculates the future  as soon as
possible or even in advance can be just as useful. My claim is only
that the difference *is* significant.

Jacob F.
unknown (Guest)
on 2006-01-10 17:44
(Received via mailing list)
Quoting A. Sanderson <removed_email_address@domain.invalid>:

> So here is a quick implementation of transparent futures in ruby.

FWIW, I've done something similar:

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

-mental
Brian McCallister (Guest)
on 2006-01-10 20:51
(Received via mailing list)
On Jan 10, 2006, at 7:41 AM, removed_email_address@domain.invalid wrote:

> FWIW, I've done something similar:
>
> http://moonbase.rydia.net/software/lazy.rb
>
> -mental

popular thing to hack on: http://kasparov.skife.org/blog/src/futures-
two.html

=)

-Brian
unknown (Guest)
on 2006-01-10 21:25
(Received via mailing list)
Quoting Brian McCallister <removed_email_address@domain.invalid>:

> two.html
It's one of those ideas whose time has come; I fully intend to
submit an RCR after a couple more releases, when the API is more
refined.

No aeroplanes bursting from the hedgerows to-day!

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