From: Daniel Berger Date: 2002-01-15T09:50:05+09:00 Subject: Re: a wishlist for ruby 2.0 I'll respond to two comments in one stroke here... "Tobias Reif" wrote in message news:3C42A3FF.9060504@pinkjuice.com... > Daniel Berger wrote: > > > > * Eliminate separate methods for "modify receiver in place" with some other > > mechanism. Either modify the receiver based on calling context (void == > > modify, rvalue == don't modify), or provide a special generic method that > > modifies the receiver. > > > Sounds interesting. Sample code? (using the new concepts, not > implementing them) First, a bit of history... One day I whined to the Perl community that I wanted to create methods for arrays, hashes and strings (all as objects, after I "blessed" them) that returned different results based on the calling context. The original dilemma was that I *always* had to return a blessed reference if I wanted to support method chaining, but being forced to de-reference every return value annoyed me to no end. First, I was told it was impossible. Then, I found the 'Want.pm' module which allowed me to do exactly what I wanted. Then, there was a bit of, "nah, nah, nah, nah...nah, nah", but I won't get into that. Here are the rules I came up with: If an object calls a method in void context, the object is modified: # receiver modified array.uniq If an object calls a method that is assigned to a variable (i.e. to an lvalue), the object is not modified: # receiver not modifed, uniq_vals contains unique values uniq_vals = array.uniq To accomplish both in one stroke, use the 'print' method (or whatever u want to call it): # receiver modified, uniq_vals contains unique values uniq_vals = array.uniq.print If a method is called as part of a chain, it modifies the receiver. Only the *last* method is checked for context. The exceptions that I made (and which you can judge for yourself): Methods that report values don't modify the receiver - mostly I'm referring to boolean methods here. Methods that are meant to explicitly delete values will delete the values, regardless of context. I have a couple more exceptions for my particular case (arrays), but I'm trying to keep it generic here. >"David Alan Black" wrote in message news:Pine.LNX.4.30.0201141607220.12386-100000@candle.superlink.net... >I don't mind the separate methods, but if I did... :-) I wouldn't want >the context to be the determinant. For one thing, you might want to >return a mapped array: > def add_three(a) > a.map {|e| e + 3} > end > where you wouldn't want the receiver automatically modified. Hopefully, my above examples make it clear that, if you assign the result, the receiver *won't* be modified. Here's some pseudo code: def add_three(a) if want.lvalue b = a.copy b.map {|e| e + 3} return b else a.map{|e| e + 3} return a end end # Would modify receiver array.add_three new_array = array.add_three.print # Would not modify receiver new_array = array.add_three >> Can you explain what you mean by a special generic method? The other solution, to cut the gordian knot so to speak, would be to just make the Ruby interpreter understand that an exclamation point at the tail of any method name indicate that the receiver should be modified in place. This would make our lives easier, but Matz's harder. That clear things up? Now, excuse me while I duck the onslaught of rotten cabbages... Regards, Dan