为什么`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语言的那一部分。
再次更新
需要明确的是:我的示例中的x
和y
不应该被解释为文字Ruby变量,它们是赋值的任何有效左侧的占位符。 x
或y
可以是任何表达式 : a
, obj.a
, CONSTANT_A
, Something::a
, @instance_a
,它们都是相同的 。 任务的价值始终是右手边。