From: Dan Doel Date: 2004-05-03T07:21:34+09:00 Subject: Re: Why no Proc##[]=() ? Why no Proc##replace() ? I understand the concept of an lvalue in assignment. I just don't think it really makes sense for proc calling. Method calls in Ruby can be lvalues, yes. However, they are used as idioms for object oriented programming. For example: a.foo = b Is used to access the foo attribute of b. That's the only way you'll have the appearance of public variables in Ruby, and otherwise you'll have to relegate yourself to a.set_foo(b) which is less pretty. []= is usually used for objects that have multiple accessible elements based on some index, like arrays and hashes. However, Proc objects don't have such indexable values. [] is an idiom for calling the Proc. Procs are like functions in Ruby, and []= would be like assigning to the result of the function, which is sort of like doing something like: 1 = a At least to my mind. It feels like treating assignment as an operation on objects, rather than an operation on variables (and it's the latter, not the former in Ruby). Would you also argue that p = lambda {...} p.call = a, b, c should be well defined? > Now, what is Proc#replace() useful for ? > > You can imagine multiple cases where the Proc itself wants to change its > own definition. For example, imagine a Proc that caches its result: > r = proc { > x = long_method > self.replace { x } > x > } > r.call() # long_method called > r.call() # cached result > > There are other ways to do this of course, without replace: > p = proc { @x ||= long_method } > or (needed if result can be nil) > p = proc { @x = long_method unless defined? @x; @x } These two work, and they don't use instance variables (which, as someone else pointed out, aren't actually the instance variables of the Proc): x = nil p = lambda { x ||= long_method } b = true r = lambda { if b then b = false; x = long_method else x end } And I don't see why this wouldn't work in this situation: x = long_method p = lambda { x } > Now, which method is more efficient ? The replace method might be more efficient if you call the Proc many times, but in the short term, I don't think either one will be wildly more efficient than the other. In fact, I'd wager that modifying the object would require more resources than doing a few boolean tests. Also, incidentally, in your example it'd have to be r.replace { x }, as self in the block is not the Proc. I guess self-modifying code could be a good thing, but it seems like overkill for caching the result of a function. :) Anyhow, that's all I can think of to say at the moment, so I'll cut this off. Cheers. - Dan