From: Michael Neumann Date: 2004-05-01T03:45:04+09:00 Subject: Lazy evaluation 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