From: Jean-Hugues ROBERT Date: 2004-05-01T05:38:03+09:00 Subject: Re: Lazy evaluation 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