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