Hi,

I am currently hacking a Packrat parser just for fun. I need to mix
values (like numbers, strings etc.) together with lazy values. I want to
make processing these values as transparent as possible.

I don't want to use something like this inside my program:

  if val.is_a? Lazy 
    val.value
  else
    val
  end

Currently, I've implemented it with a ValueHolder class, and a Lazy
class, both implementing the #value protocol:

  class Lazy
    def self.[](*args, &block)
      new(*args, &block)
    end

    def initialize(*args, &block)
      raise "no block given" if block.nil?
      @block = block
      @block_evaluated = false
      @args = args
    end

    def value
      if @block_evaluated
        @value
      else
        @block_evaluated = true
        @value = @block.call(*@args)
        @block = @args = nil # free memory
        @value
      end
    end
  end
  class ValueHolder
    attr_accessor :value

    def self.[](*args, &block)
      new(*args, &block)
    end

    def initialize(value)
      @value = value
    end
  end

But then I have to use the value method very often and the actions the
user of the packrat parser writes becomes hard to understand due to very
high usage of #value.

Another possible solution would be to use a LazyDelegator. But that too
has some disadvantages, e.g. when doing many calculations on this value,
or passing the value to some extension that requires this to be a String
etc.. The ultimate solution would be a LazyDelegator which then turns
into the actual value. IIRC, Smalltalk had some command with which an
object could turn into some other object?

Actually, what I'd like to have is:

  a = 5
  a.becomes("a string")
  a #=> "a string"

Any comments or suggestions?

Regards,

  Michael