From: mame@... Date: 2018-04-26T06:03:49+00:00 Subject: [ruby-core:86692] [Ruby trunk Feature#14701] If the object is not frozen, I want to be able to redefine the compound assignment operator. Issue #14701 has been updated by mame (Yusuke Endoh). I agree with matz and eregon. Honestly, I first thought that it was a good idea to split `+` and `+=`. But by investigating Python, I now think that it easily leads to strange behavior. One example is what eregon and sonots said: ``` >>> a = [] >>> b = a >>> a += [1,2,3] >>> b [1, 2, 3] ``` Most Rubyists know and expect that `Array#+` is non-destructive, so I think that it is unacceptable to allow this. Another example is the following that is Python's actual result. I don't want to see this in Ruby. ``` >>> a = [] >>> a += "foo" >>> a ['f', 'o', 'o'] ``` ``` >>> a = [] >>> a + "foo" Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate list (not "str") to list ``` If I explain this behavior in Ruby terminology, `Array#+=` accepts any Enumerable, but `Array#+` does not. Note that this spec design itself is somewhat reasonable. `Array#+` accepts only an Array because, is it accepts an Enumerator, it is ambiguous what it should return, Array or Enumerator. On the other hand, this does not matter for `Array#+=` because an assignment returns no value in Python. So, I think that these Python's behavior is indeed intentional. But actually strange. IMO, the fundamental flaw is to split `+` and `+=`. sonots (Naotoshi Seo) wrote: > ANOTHER IDEA: > How about allowing to redefine `+!` instead of `+=` although it looks not intuitive for me, but it would be a ruby way. Do you mean introducing another set of destructive operators, like `a +! 1` instead of `a += 1`? It is not very cool, but it seems more reasonable to me. ---------------------------------------- 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-71650 * Author: naitoh (Jun NAITOH) * Status: Rejected * 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: