为什么a Ruby setter return 是传递的值,而不是实例变量的最终值?
Why does a Ruby setter return the passed value, rather than the final value of the instance variable?
通常,Ruby 方法 return 方法中最后一个表达式的值。然而,对于 name=
形式的 setter,它似乎是
给定以下代码:
class Foo
attr_reader :bar
def set_bar(v)
@bar = (v + 1)
end
def bar=(v)
@bar = (v + 1)
end
end
如果我调用 bar=
或 set_bar()
,@bar
的值是相同的:
f = Foo.new; f.set_bar(1); f.bar
# => 2
f = Foo.new; f.bar=1; f.bar
# => 2
然而,二传手的 return 价值观不同:
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 没有遵循最小惊奇原则)并且没有在任何地方明显记录。它有记录吗?有什么原因吗?
所有赋值总是计算到右侧。不管是不是a
局部变量赋值:
foo = 42 #=> 42
实例变量赋值
@foo = 42 #=> 42
class变量赋值
@@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
请注意 return 值 而不是 完全忽略:
f.public_send(:bar=, 1)
#=> 2
Is it documented?
我最喜欢的关于此类问题的文档是 ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification。您要查找的部分是 11.4.2.2.5 单一方法分配.
Is there a reason for it?
(matz's) 最小惊奇的一致性和原则:所有其他赋值在 Ruby 中计算到右侧。事实上,在几乎所有以表达式为赋值的语言中,赋值都计算在右侧。
因此,方法赋值也计算到它们的右侧是有意义的。
通常,Ruby 方法 return 方法中最后一个表达式的值。然而,对于 name=
形式的 setter,它似乎是
给定以下代码:
class Foo
attr_reader :bar
def set_bar(v)
@bar = (v + 1)
end
def bar=(v)
@bar = (v + 1)
end
end
如果我调用 bar=
或 set_bar()
,@bar
的值是相同的:
f = Foo.new; f.set_bar(1); f.bar
# => 2
f = Foo.new; f.bar=1; f.bar
# => 2
然而,二传手的 return 价值观不同:
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 没有遵循最小惊奇原则)并且没有在任何地方明显记录。它有记录吗?有什么原因吗?
所有赋值总是计算到右侧。不管是不是a
局部变量赋值:
foo = 42 #=> 42
实例变量赋值
@foo = 42 #=> 42
class变量赋值
@@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
请注意 return 值 而不是 完全忽略:
f.public_send(:bar=, 1)
#=> 2
Is it documented?
我最喜欢的关于此类问题的文档是 ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification。您要查找的部分是 11.4.2.2.5 单一方法分配.
Is there a reason for it?
(matz's) 最小惊奇的一致性和原则:所有其他赋值在 Ruby 中计算到右侧。事实上,在几乎所有以表达式为赋值的语言中,赋值都计算在右侧。
因此,方法赋值也计算到它们的右侧是有意义的。