我正在运行ruby 1.9.2p180(2011-02-18修订版30909)[x86_64-linux]。
#!/usr/bin/env ruby
def ouch()
raise ArgumentError, "woof"
fred = 3
return( nil )
ensure
if ( defined?( fred ) ) then
printf( "fred is defined (%s)\n", fred.inspect() )
else
printf( "fred is not defined\n" )
end
end # ouch()
ouch()
运行时,上面ruby脚本的输出非常意外。
$ ./ouch.rb
fred is defined (nil)
./ouch.rb:4:in `ouch': woof (ArgumentError)
from ./ouch.rb:22:in `<main>'
因此,加注/异常正在发生,fred并未设置为3,但是 它被定义并设置为零,从而打败了测试 定义?()。这非常令人困惑。这是一个错误吗?显然是考验 对于定义的需求,测试不是零。
如果这不是一个错误,有人可以解释原因吗?
答案 0 :(得分:7)
Ruby中的局部变量是在它们首次使用的行和当前词法范围的末尾之间定义的。它们也被隐式初始化为nil
。
还要考虑这个例子:
if false
var = 123
end
p var # => nil
此行为是有意的。 Ruby的设计方式可以区分方法调用和解析步骤的局部变量访问,而非执行步骤。因此,在定义变量之后,对该名称的所有进一步引用都将访问该变量,无论它是否显式设置为某个值。
(如果有人将我指向Ruby中的CALL_VCALL方法调用类型,我会回答一下,据我所知,它只在eval
中使用:当你{{1}时你不能从头开始知道是否在irb的前一行定义了一些变量,因此应该捕获并相应地调度这些访问。)
答案 1 :(得分:4)
这是一个更简单的例子:
if false
alocal = 123
end
p defined? alocal
=> "local-variable"