Hi --

On Wed, 18 Aug 2004, Brian Palmer wrote:

> David A. Black wrote:
> 
> > Hi --
> >
> > On Wed, 18 Aug 2004, Brian Palmer wrote:
> >
> >  
> >
> >> So yeah, the whole "on_#{arg}= a" thing is a hack, but += doesn't
> >> behave as I would expect when used after a method.  I would think it
> >> would call the method first, and then call += on its return value.
> >> But it calls the method, calls + on its return value, then calls the
> >> method= version of the method.
> >>   
> >
> >
> > The way you're describing can't really work, though; you'd end up with
> > the problem of altering immutable values (the same thing that has led
> > Matz not to have a ++ operator):
> >
> >  obj.x = 1
> >  obj.x += 1  # would resolve to: 1 += 1, which is: 1 = 1 + 1
> >
> > The syntactic sugar transformation (a += b to a = a + b) has to happen
> > before anything else happens that could turn the lhs into a
> > non-l-value.
> >
> >
> > David
> >  
> >
> That's true.  I figured there was a reason for it, just wasn't sure 
> what.  So it couldn't be set up to simply throw a run-time error 
> exception if you try to alter an immutable value in this way?  Or it 
> could, but it would take a lot of time/make things slower?  Just trying 
> to understand things better...

I guess it's just a case of not making a special case :-) a += b is
always parsed as a = a + b, whether it involves local variables or
methods.  This also harmonizes, I think, with the goal of the "="
pseudo operator overall, namely to unify the syntax as between
variable assignment and calling of "=" methods as much as possible.

Another thing is that the occasions when it would be either harmful or
useless to call the method first is pretty large.  Other than the
1 = 1 + 1 case, consider also:

  class A
    attr_writer :s
    def s
      @s.dup
    end
  end

(Dup'ing an object in a read method is far from unheard-of, as a way
of protecting the actual object from being modified.)

  a = A.new
  obj.s = "hello"
  obj.s += " there"

If the method obj.s is run first, one of two things happens.  You'd
actually be doing:

  "hello" += "there"

So either it doesn't parse (because "hello" isn't an l-value), or +=
takes on a new (and suspiciously magic) meaning and we end up with
"hello there" -- which then gets thrown away, because we haven't
assigned it to anything.  (Remember, the whole point is that we're
*not* calling the A#s= method.) 


David

-- 
David A. Black
dblack / wobblini.net