在红宝石中,为什么没有定义?与确保一起使用时可以预期的工作

时间:2011-08-07 17:57:33

标签: ruby

我正在运行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,但是 它被定义并设置为零,从而打败了测试 定义?()。这非常令人困惑。这是一个错误吗?显然是考验 对于定义的需求,测试不是零。

如果这不是一个错误,有人可以解释原因吗?

2 个答案:

答案 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"