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

请考虑以下代码段:

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

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

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

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

更新:感谢@jeffgran:

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

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

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

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


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

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

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

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

……我们写这个……

 if obj.x = getExpensiveThing() 

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

更新

对该问题的评论指出:

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

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

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

再次更新

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