From: Jean-Hugues ROBERT Date: 2002-06-11T18:57:50+09:00 Subject: Re: def += Hello, At 02:53 11/06/2002 +0900, you wrote: >On Tue, Jun 11, 2002 at 02:41:04AM +0900, Kontra, Gergely wrote: > > Hi! > > > > I've successfully redefined the + method, the <=> method in some > > classes, but when I tried the same with +=, it doesn't work. > > (I use ruby 1.6.6) > > > > Eg.: > > class Hash > > def +=(other) > > {} # dummy > > end > > end > > > > gives: > > SyntaxError: compile error > > def +=(other) > > ^ > > (irb):5: parse error > > > > Then, my Q is how to (re)define the += operator (method)). > >It's simply not possible! > >When you define a + operator, Ruby automatically "adds" a += operator >which behaves like a = a + b. > >Regards, > > Michael How is that += automatically generated (if at all) ? If figured out that it could be done using a .clone() and a .replace(v) that the user would still have to provide (I was wrong, read further). Having += behavior automatically changed when one redefines + is cool! I wondered why it does not *also* work the other way around (i.e. +() changed when user defines +=()) ? The result could sometimes be much more efficient: Here is a (dense) example dealing with files: class LargeFile # Case 1: where User redefines +() def fname() id.to_s end def to_s() File.open(fname,"r"){|x|x.gets} end def replace(v) File.open(fname,"w"){|x|x.write v.to_s}; self end def clone() LargeFile.new.replace self end def +(a) c=clone; File.open(c.fname,"w+"){|x|x.write a.to_s}; c end # Presumably automatically generated code ? def +=(a) replace( self + a) end end class LargeFile # Case 2: where User redefines +=() def fname() id.to_s end def to_s() File.open(name,"r"){|x|x.gets} end def clone() LargeFile.new() += self end def +=(a) File.open(fname,"w+"){|x|x.write a.to_s}; self end # Presumably automatically generated code def +(a) self.clone += a end end The efficiency of +() is the same in both cases. However the efficiency of +=() is better in case 2 because case 1 requires the creation of a new object (by +()) whereas it is directly self that gets modified in case 2. I then wondered: Why would a language favor a scheme so obviously less efficient ? Well... Ruby does what's necessary. I had a look at the mailing list archive. Turns out that: 1) There is apparently no such thing as a "generated" += method 2) a += b is actually 100% equivalent to a = a + b 3) a = "a"; b = a; a += b; p a, b => "aa" "a" 4) a = "a"; b = a; a << b; p a, b => "ab" "ab" 5) When speed matters, use <<, not +, not += However: check page 549 of Syngress's book "RUBY Developer's Guide" 6) += has "value" semantic, << has "object semantic" 7) Infering +() from +=() only... is impossible: a copy constructor (a la C++) or .clone() (a la Smalltalk) is needed. 8) This is all related to Mutability I guess. See http://www.c2.com/cgi/wiki?ValueObjectsShouldBeImmutable Yours, Jean-Hugues ------------------------------------------------------------------------- Web: http://hdl.handle.net/1030.37/1.1 Phone: +33 (0) 4 92 27 74 17