ruby, define []= operator, why can't control return value?
Trying to do something weird that might turn into something more useful, I tried to define my own []=
operator on a custom class, which you can do, and have it return something different than the value
argument, which apparently you can't do. []=
operator's return value is always value
; even when you override this operator, you don't get to control the return value开发者_StackOverflow社区.
class Weird
def []=(key, value)
puts "#{key}:#{value}"
return 42
end
end
x = Weird.new
x[:a] = "a"
output "a:a"
return value => "a" # why not 42?
Does anyone have an explanation for this? Any way around it?
ruby MRI 1.8.7. Is this the same in all rubys; Is it part of the language?
Note that this behavior also applies to all assignment expressions (i.e. also attribute assignment methods: def a=(value); 42; end
).
My guess is that it is designed this way to make it easy to accurately understand assignment expressions used as parts of other expressions.
For example, it is reasonable to expect x = y.a = z[4] = 2
to:
- call
z.[]=(4,2)
, then - call
y.a=(2)
, then - assign
2
to the local variablex
, then finally - yield the value
2
to any “surrounding” (or lower precedence) expression.
This follows the principle of least surprise; it would be rather surprising if, instead, it ended up being equivalent to x = y.a=(z.[]=(4,2))
(with the final value being influenced by both method calls).
While not exactly authoritative, here is what Programming Ruby has to say:
Programming Ruby (1.8), in the Expressions section:
An assignment statement sets the variable or attribute on its left side (the lvalue) to refer to the value on the right (the rvalue). It then returns that value as the result of the assignment expression.
Programming Ruby 1.9 (3rd ed) in section 22.6 Expressions, Conditionals, and Loops:
(right after describing
[]=
method calls)The value of an assignment expression is its rvalue. This is true even if the assignment is to an attribute method that returns something different.
It’s an assignment statement, and those always evaluate to the assigned value. Making this different would be weird.
I suppose you could use x.[]= :a, "a"
to capture the return value.
精彩评论