[翻译]  Why isn't `method=` treated the same as any other method?

[CHINESE]  为什么`method =`与其他方法一样处理?


Consider the following code snippet:

请考虑以下代码段:

class Example
  def my_attr=(value)
    @_my_attr = value
    @_my_attr * 3
  end
end

I expect the expression Example.new.my_attr = 5 to return 15, but that turns out to be wrong. The original return value is always returned, even when I call the = method explicitly:

我希望表达式Example.new.my_attr = 5返回15,但结果证明是错误的。即使我明确调用=方法,也始终返回原始返回值:

Example.new.my_attr = 5 # => 5
Example.new.my_attr=(5) # => 5

How and why does Ruby do this? Does Ruby treat methods that end in = specially, or is it some other mechanism? I guess this precludes chaining on return values of = methods, right? Is there a way to make Ruby behave differently, or is this just how it is?

Ruby如何以及为什么这样做? Ruby是否处理以特殊结尾的方法,还是其他机制?我想这排除了链接=方法的返回值,对吗?有没有办法让Ruby的行为不同,或者这是怎么回事?

Update: Credit to @jeffgran for this:

更新:感谢@jeffgran:

Example.new.send(:my_attr=, 5) # => 15

This is a workaround, but on another level even more perplexing, since that would mean send is clearly not always equivalent in behavior to calling a method directly.

这是一种解决方法,但在另一个层面上更令人困惑,因为这意味着发送显然并不总是等同于直接调用方法的行为。

1 个解决方案

#1


19  

This is how assignment works; the return value is ignored, and the result of an assignment expression is always the right-hand value. This is a fundamental feature of Ruby's grammar. left-hand side = right-hand side will always evaluate to right-hand side, regardless of whether left hand side is a variable (x), a method (object.x), a constant (X) or any expression.

这就是作业的工作原理;返回值被忽略,赋值表达式的结果始终是右侧值。这是Ruby语法的基本特征。左侧=右侧将始终评估到右侧,无论左侧是变量(x),方法(object.x),常量(X)还是任何表达式。

Source: Programming Languages | Ruby IPA Ruby Standardization WG Draft, 11.4.2.2.5, Single method assignments

来源:编程语言| Ruby IPA Ruby Standardization WG Draft,11.4.2.2.5,Single method assignment


Consider chaining of assignments, x = y = 3.

考虑分配链接,x = y = 3。

For this to work correctly, the result of y = 3 must be 3, regardless of the actual value returned by the y= method. x = y = 3 is meant to read as y = 3; x = 3, not as y = 3; x = y which is what would be implied if the return value from y= was treated as the result of y = 3.

为了使其正常工作,y = 3的结果必须为3,而不管y =方法返回的实际值。 x = y = 3意味着读作y = 3; x = 3,而不是y = 3; x = y如果来自y =的返回值被视为y = 3的结果,则暗示该含义。

Or consider all the other places assignment can be used. Sometimes, instead of this...

或者考虑可以使用所有其他地方的分配。有时候,而不是......

obj.x = getExpensiveThing()
if obj.x 
  ...

... we write this ...

......我们写这个......

if obj.x = getExpensiveThing()

This couldn't work if the result of obj.x = ... could be any arbitrary thing, but we know it will work because the result of obj.x = y is always y.

如果obj.x = ...的结果可能是任意的,那么这不起作用,但是我们知道它会起作用,因为obj.x = y的结果总是y。

Update

更新

A comment on the question states:

对该问题的评论指出:

Interesting, I wasn't aware of this scenario. It seems that method= returns whatever input is given...

有趣的是,我不知道这种情况。似乎method =返回给出的任何输入...

No, it's an important distinction to make. This has nothing to do with the return value of method assignment, and it definitely does not "return whatever input is given", it returns whatever you tell it to return.

不,这是一个重要的区别。这与方法赋值的返回值无关,它肯定不会“返回给出的任何输入”,它返回你告诉它返回的任何内容。

The whole point is that the return value is ignored by the grammar of the language; assignment doesn't evaluate to the return value of the attr= method, but the return value still exists as evidenced by the question itself: Example.new.send(:my_attr=, 5) # => 15. This works because it is not assignment. You're side-stepping that part of the Ruby language.

重点是语言的语法忽略了返回值;赋值不会计算为attr =方法的返回值,但返回值仍然存在,如问题本身所示:Example.new.send(:my_attr =,5)#=> 15.这是有效的,因为它是不是任务。你是踩着Ruby语言的那一部分。

Update again

再次更新

To be clear: x and y in my examples shouldn't be interpreted as literal Ruby variables, they are place holders for any valid left-hand side of an assignment. x or y could be any expression: a, obj.a, CONSTANT_A, Something::a, @instance_a, it's all the same. The value of assignment is always the right-hand side.

需要明确的是:我的示例中的x和y不应该被解释为文字Ruby变量,它们是赋值的任何有效左侧的占位符。 x或y可以是任何表达式:a,obj.a,CONSTANT_A,Something :: a,@ instance_a,它们都是相同的。任务的价值始终是右手边。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2018 ITdaan.com 粤ICP备14056181号