我想在ActiveInteraction中使用经典的|| =重新分配(cf Set Ruby variable if it is not already defined),就像在https://github.com/AaronLasseigne/active_interaction/issues/395中一样
但是,通过在ActiveInteraction中测试不同的语法,我偶然发现了一个甚至在Vanilly Ruby中也发生过的更奇特的问题。
未执行的行(由if false
阻止)仍然会对其余代码产生重大影响:
class A
attr_accessor :a
def run
(puts defined? a; a) if true
end
def run2
(puts 'change a'; a = 0) if false
puts defined? a
a
end
end
x = A.new
x.run # "method"; nil
x.run2 # "local-variable"; nil
x.a = 5
x.run # "method"; 5
x.run2 # "local-variable"; nil
任何人都可以解释这是错误还是功能?如果有一个功能:怎么来?看起来很奇怪。
编辑:感谢@Sergio Tulentsev的回答,我设法发现我的问题与Ruby instance method & conditional local variable assignment with same name几乎完全相同,但标题名称的重点不同。
答案 0 :(得分:3)
[这]是错误还是功能?
都不是。这是...特殊性。发生的是,当解析器在代码中看到分配给局部变量的代码时,它将继续进行操作并将名称添加到作用域(从该行开始,可能会覆盖其他名称,例如此处的方法)。默认值为nil
。如果实际的赋值从未执行过,则新的局部变量仍在作用域内,并且仍求值为nil
。
这在https://docs.ruby-lang.org/en/2.5.0/syntax/assignment_rdoc.html#label-Local+Variables+and+Methods中有记录。