At 03:45 01/05/2004 +0900, you wrote:
>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

Comments ? Not much. Besides the fact that we both need some kind of a 
Reference class to inherit from.

You to do:
class LazyValue < Reference
...

Me to do:
class LogicVariable < Reference

In both cases we want automatic dereferencing of the object when its
value is required.

As far as I know the least intrusive notation is to use the [] and []=
accessors that you can redefine. Be carefull with []=, the assigned
value is not under its control (use xx.[]= yy syntax instead).

I expect soon to have the issue striking again while implementing
"Future". Kind of lazy evaluation. A "Future" is the result of a
method call that is not available yet, but you don't mind, until
you need it, then you block until it is available. That is a
useful concept for distributed computing.

BTW: I too miss Smalltalk's becomes(). Sometimes you can use
.replace(), but it is not as general (you can change the value,
not the class).

Yours,

Jean-Hugues



-------------------------------------------------------------------------
Web:  http://hdl.handle.net/1030.37/1.1
Phone: +33 (0) 4 92 27 74 17