Issue #10570 has been updated by David MacMahon.


Yukihiro Matsumoto wrote:
> `Array#[]=` can be defined by alternation of elements of an array, which does not contain any assignment to variables. That's the reason that can be implemented by a method. In contrast, `a += b` includes assignment in its semantic, especially in a language like Ruby that has uniform reference model (unlike languages like C++).
> 
> Besides that, replacing `+=` etc by methods would slow down those assignments significantly. I don't want that neither.

Fair enough, but then what about  `#<attr><op>=` methods?  it seems like `foo.bar += 1` could be similar to the `a[i] = b` case because it is not assigning `foo` itself.  Instead it could alter an attribute of `foo` by calling the `#bar+=` method.  I guess supporting that would create problems for existing code that expects the current behavior.  I'll stop pursuing this now.

Thanks again,
Dave

----------------------------------------
Feature #10570: Allow `+=` etc. to be methods
https://bugs.ruby-lang.org/issues/10570#change-50318

* Author: David MacMahon
* Status: Rejected
* Priority: Normal
* Assignee: 
* Category: 
* Target version: 
----------------------------------------
In MRI, it is currently possible to create `#+=` methods in C extensions and even `+=` aliases for existing methods in Ruby source code.  These methods are only callable via `#send('+=', ...)` because the parser interprets `a += b` as `a = a + b` before the "operator method" is called.  Thus, `a += b` is currently equivalent to `a = a.send('+', b)` rather than `a.send('+=', b)`.  This feature request is to allow and support `<OP>=` methods, where `<OP>` is any of Ruby's operators that can be defined as methods (e.g. `#+`, `#-`, etc).

A related feature request would be to allow `#<attribute><op>=` methods in addition to the already supported`#<attribute>=` methods.  As it is now, `foo.bar += x` is equivalent to `foo.send('bar=', foo.send('bar').send('+', x))`, which requires that the return value of `foo.bar` implements `#+` and that `foo` implements `#bar=`.  If this related feature were implemented, `foo.bar += x would be equivalent to `foo.send('bar+=', x)`.

I guess this would be tricky to add in a backwards compatible way.  What happens if `#+=` is not defined for the would-be receiver?  How would that condition be detected in a way that could fall back to the old default behavior?

What other possible complications could make this request impractical?



-- 
https://bugs.ruby-lang.org/