我正在运行
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,但是
它被定义并设置为零,从而打败了测试
定义?().这非常令人困惑.这是一个错误吗?显然是考验
对于定义的需求,测试不是零.
如果这不是一个错误,有人可以解释为什么不呢?
解决方法
Ruby中的局部变量是在它们首次使用的行和当前词法范围的末尾之间定义的.他们也被隐含地初始化为零.
还要考虑这个例子:
if false var = 123 end p var # => nil
此行为是有意的. Ruby的设计方式可以在解析步骤中区分方法调用和局部变量访问,而不是执行一次.因此,在定义变量的点之后,对该名称的所有进一步引用都将访问该变量,无论它是否显式设置为某个值.
(如果有人将我指向Ruby中的CALL_VCALL方法调用类型,我会回答说,据我所知,它仅用于eval:当你进行评估时,你无法从一开始就知道某个变量是什么在上一行的irb中定义,因此应该相应地捕获和发送这样的访问.)