Issue #14701 has been updated by jwmittag (Jrg W Mittag).


It is possible to find sane semantics for this. Scala, for example, has the following semantics:

```scala
a = b
```

is first tried to be interpreted as 

```scala
a.=(b)
```

and if that fails, it is interpreted as 

```scala
a = a.(b)
```

[Note: `` here is any sequence of operator characters.]

It would be possible to apply the same semantics of Ruby. This would allow to keep the current strict separation between *variables* and *values* as well as *variables* and *messages* in place.

There are other languages, where assignment is always a message send, but this requires much more fundamental changes to how Ruby works. In particular, it would require either giving up the distinction between *variables* and *values* or the distinction between *variables* and *messages*.

For example, in [Newspeak](https://newspeaklanguage.org/), there are no variables. When you define what *looks like* an instance variable, what you are *actually* defining as an unnamed, unaccessible, hidden *slot* and a pair of getter and setter methods for that slot. Imagine Ruby's `attr_accessor` / `attr_reader` / `attr_writer` but without the ability to refer to instance variables directly using `@`. All other kinds of "variables" are then reduced to "instance variables", i.e. to getter / setter methods. Class variables are simply instance variables on the class object, local variables are instance variables on the stack frame object, and global variables simply don't exist.

In [Ioke](https://ioke.org/), assignment is what the author calls a "trinary operator", i.e. an operator that *looks* binary (has two operands) but is actually ternary (has a hidden third operand). So, 

```ioke
a = b
```

is actually equivalent to 

```ioke
=(a, b)
```

i.e. a message send of the message `=` with arguments `a` and `b` to the current receiver (which is however subtly different from Ruby's `self`), called the current "Ground" in Ioke. This however only works because a) the current Ground is a subtly different concept from `self` in Ruby (objects are not only dynamic scopes but also lexical scopes), b) because in Ioke, method arguments are passed un-evaluated (think "AST", but also subtly different), and c) "places" (storage space) are an actual reified language concept.

Both of these solutions would be a *major* departure from Ruby as it exists currently, and while both of these approaches are very powerful and beautifully simple, it is just not feasible to do anything like this in Ruby.

So, the only possible solution is the Scala solution: try `a.=(b)` first and if that fails, do `a = a  b`.

Note, however, that there is no way around the fact that whatever we choose to do, this *will* be backwards-incompatible! There is no way of introducing this feature that will *not* change the behavior of the following code:

```ruby
class Foo
  def +(*) 23 end
  def method_missing(*) 42 end
end

a = Foo.new
a += nil
a
```

Currently, this will call `Foo#+` and re-assign `a`, if this change is implemented, it will call `Foo#method_missing` and *not* re-assign `a`.

Before:

```ruby
a += nil
#=> 23

a #=> 23
```

After:

```ruby
a += nil
#=> 42

a #=> #<Foo:0xdeadbeef>
```

----------------------------------------
Feature #14701: If the object is not frozen, I want to be able to redefine the compound assignment operator.
https://bugs.ruby-lang.org/issues/14701#change-80620

* Author: naitoh (Jun NAITOH)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
If the object is not frozen, I want to be able to redefine the compound assignment operator (e.g. +=, -=, *=, /=, ..etc ).

https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html

* Redefinable operator (method) 

~~~
    |  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
    +  -  *  /    %   **   ~   +@  -@  []  []=  ` ! != !~
~~~

* use case

~~~
> require 'numo/narray'
> a = Numo::Int32[5, 6]
=> Numo::Int32#shape=[2]
[5, 6]
> a.object_id
=> 70326927544920
> a += 1
=> Numo::Int32#shape=[2]
[6, 7]
> a.object_id
=> 70326927530540
> a.inplace + 1
=> Numo::Int32(view)#shape=[2]
[7, 8]
> a.object_id
=> 70326927530540
~~~

With Numo::NArray, using "inplace" instead of "+=" will update the same object so it will be faster.

I want to write "a += 1" instead of "a.inplace + 1".
However, Ruby can not redefine "+=".



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

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>