ruby - 为什么 Ruby setter 返回传递的值,而不是实例变量的最终值?
问题描述
通常,Ruby 方法返回方法中最后一个表达式的值。然而,对于 form 的 setter name=
,它看起来像
给定以下代码:
class Foo
attr_reader :bar
def set_bar(v)
@bar = (v + 1)
end
def bar=(v)
@bar = (v + 1)
end
end
如果我调用bar=
or set_bar()
,则值@bar
是相同的:
f = Foo.new; f.set_bar(1); f.bar
# => 2
f = Foo.new; f.bar=1; f.bar
# => 2
然而,setter 的返回值是不同的:
f = Foo.new; f.set_bar(1)
# => 2
f = Foo.new; f.bar = 1
# => 1
# note: irb in Ruby 2.7+ suppresses this unless you write (f.bar = 1)
即使我添加了一个明确的,这仍然存在return
:
class Foo
def bar=(v)
@bar = (v + 1)
return @bar
end
end
f = Foo.new; f.bar = 1
# => 1
这很令人惊讶(我知道,Matz 明确表示 Ruby 不遵循最小意外原则),并且在任何地方都没有明显的记录。是否记录在案?有什么原因吗?
解决方案
所有的分配总是在右手边求值。不管是不是一个
局部变量赋值:
foo = 42 #=> 42
实例变量赋值
@foo = 42 #=> 42
类变量赋值
@@foo = 42 #=> 42
全局变量赋值
$foo = 42 #=> 42
常量赋值
FOO = 42 #=> 42
缩写作业
foo += 42 #=> 42 foo -= 42 #=> 42 foo *= 42 #=> 42 foo /= 42 #=> 42 foo %= 42 #=> 42 foo <<= 42 #=> 42 foo >>= 42 #=> 42 foo |= 42 #=> 42 foo &= 42 #=> 42 foo ||= 42 #=> 42 foo &&= 42 #=> 42
方法分配
foo.bar = 42 #=> 42
请注意,返回值不会被完全忽略:
f.public_send(:bar=, 1)
#=> 2
是否记录在案?
对于此类问题,我最喜欢的文档是ISO/IEC 30170:2012信息技术 — 编程语言 — Ruby规范。您正在寻找的部分是 11.4.2.2.5 Single method assignments。
有什么原因吗?
(matz's) Least Astonishment 的一致性和原则:在 Ruby 中,所有其他作业都在右侧计算。事实上,在几乎所有赋值是表达式的语言中,赋值都在右侧计算。
因此,方法分配也对它们的右侧进行评估是有意义的。
推荐阅读
- node.js - Sequelize 关系中的查询
- c# - 按空格分割字符串,需要说明
- sql - 如何显示我没有得到“在预期条件的上下文中指定的非布尔类型的表达式”的 2 个城市
- javascript - 错误:目标容器不是 DOM 元素 react /react-redux
- angular - 是否建议订阅管道内的商店(ngRx)?
- sprite-kit - 减少 SpriteKit 中的绘制次数(通过次数)
- c# - 给定用户输入的数组队列
- flutter - 颤动的信用卡扫描仪
- javascript - 第 1 组正则表达式匹配的 matchAll 数组
- postgresql - 如何获取所有在某处半径内以及我正在寻找的半径内的数据?