Hi,

At Sat, 27 Jul 2002 13:12:37 +0900,
Reginald Braithwaite-Lee wrote:
> Has there been any work on using Ruby's closures to implement
> call-by-need semantics, such as the freeze and thaw or delay and force
> macros in Lisp?

Like this?

# udelegator.rb by kjana [ruby-list:8239]
class UDelegator
  def initialize(obj)
    preserved = ::Kernel.instance_methods
    for t in self.type.ancestors
      preserved |= t.instance_methods
      break if t == UDelegator
    end
    preserved -= ["__getobj__","to_s","nil?","to_a","hash","dup","==","=~"]
    for method in obj.methods
      next if preserved.include? method
      undef_method method
    end
  end

  def method_missing(msg, *arg, &block)
    __getobj__.__send__(msg, *arg, &block)
  end

  def __getobj__
    raise NotImplementError, "need to define `__getobj__'"
  end
end

class Promise <UDelegator
  def initialize
    @proc = Proc.new
  end

  def __getobj__
    return @obj if @obj
    @obj = @proc.call
  end
end

def delay(&block)
  Promise.new(&block)
end

class Future <UDelegator
  def initialize(&block)
    @th = Thread.new(&block)
    @th.abort_on_exception
  end

  def __getobj__
    return @obj if @obj
    @obj = @th.value
  end
end

def future(&block)
  Future.new(&block)
end

if __FILE__ == $0
  class Foo
    def initialize(a); @a = a; end
    def [](i); @a[i]; end
    def []=(i, v); @a[i] = v; end
    def isa; type; end
  end

  puts "promise example"
  foo = delay {a = Foo.new([]); for i in 1..100; print "#{i} "; a[i] = i; end; puts; a}
  puts "here is `non touched' promise #{foo}"
  puts "# preserved method call: promise is not evaluated here."
  puts "foo.type = #{foo.type}"
  puts "# unpreserved method call: promise is `touched' here."
  puts "foo.isa = #{foo.isa}"
  puts "foo[10] = #{foo[10]}"

  puts

  puts "future example"
  st = 15
  st = ARGV.shift.to_i if ARGV.size > 0
  foo = future {sleep 10; a = Foo.new([]); for i in 1..100; print "#{i} "; a[i] = i; end; puts; a}
  puts "here is `non touched' future #{foo}"
  puts "# preserved method call: future is not evaluated here."
  puts "foo.type = #{foo.type}"
  puts "some time consuming task take place...."
  sleep st;
  puts "# unpreserved method call: future is `touched' here."
  puts "foo.isa = #{foo.isa}"
  puts "foo[10] = #{foo[10]}"
end

-- 
Nobu Nakada