Project

General

Profile

Feature #10570

Allow `+=` etc. to be methods

Added by david_macmahon (David MacMahon) about 5 years ago. Updated about 5 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:66706]

Description

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 tofoo.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?

History

Updated by matz (Yukihiro Matsumoto) about 5 years ago

  • Status changed from Open to Rejected

a+=b is a short hand form of a = a + b by definition. It's fundamentally an assignment. Target of assignment (including += etc) is a variable, not an object. It cannot be implemented by a method.

For example, how can we define Integer#+=?

Matz.

Updated by david_macmahon (David MacMahon) about 5 years ago

Thanks for your thoughtful reply!

Yukihiro Matsumoto wrote:

a+=b is a short hand form of a = a + b by definition. It's fundamentally an assignment. Target of assignment (including += etc) is a variable, not an object. It cannot be implemented by a method.

I agree that a = a + b is fundamentally an assignment (and I'm not asking for an assignment operator :-)). I'm not sure that the definition of a += b as a short hand form of a = a + b is quite so fundamental. Definitions can be redefined.

What about a[i] = b? That is (or at least looks like) a form of assignment that is already implemented as a method.

For example, how can we define Integer#+=?

Immutable classes would simply not define a += method. For example, we already have Fixnum#[] without Fixnum#[]=.

Dave

Updated by david_macmahon (David MacMahon) about 5 years ago

David MacMahon wrote:

Yukihiro Matsumoto wrote:

For example, how can we define Integer#+=?

Immutable classes would simply not define a += method

...and the current behavior would be used for lvalues not implementing a += method. That's the tricky part I was referring to in the original post.

Dave

Updated by matz (Yukihiro Matsumoto) about 5 years ago

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.

Matz.

Updated by david_macmahon (David MacMahon) about 5 years ago

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

Also available in: Atom PDF