【问题标题】:Ruby eval behaves differently in irb versus in a fileRuby eval 在 irb 和文件中的行为不同
【发布时间】:2009-04-03 18:00:13
【问题描述】:

此代码在 irb 中有效:

irb(main):037:0> eval <<-EOS
irb(main):038:0" #{attribute} = "host"
irb(main):039:0" puts machine
irb(main):040:0" EOS
host
=> nil
irb(main):041:0> puts machine
host
=> nil
irb(main):042:0> puts attribute
machine
=> nil
irb(main):043:0>

但是,当我尝试执行与 ruby​​ 脚本相同的代码时,出现以下错误:

../autosys/convert_jil_to_zapp.rb:40: undefined local variable or method `machine' for main:Object (NameError)
        from ../autosys/convert_jil_to_zapp.rb:29:in `each_line'
        from ../autosys/convert_jil_to_zapp.rb:29
        from ../autosys/convert_jil_to_zapp.rb:27:in `each'
        from ../autosys/convert_jil_to_zapp.rb:27
pi929c1n10 /ms/user/h/hirscst/ruby/autosys 77$ gvim try.rb
pi929c1n10 /ms/user/h/hirscst/ruby/autosys 78$ chmod +x try.rb
pi929c1n10 /ms/user/h/hirscst/ruby/autosys 79$ ./try.rb
host
./try.rb:8: undefined local variable or method `machine' for main:Object (NameError)

谁能解释一下原因?

【问题讨论】:

    标签: ruby eval


    【解决方案1】:

    这是因为在运行 eval 时尚未定义 machine 变量。一个更简洁的例子:

    在 IRB 中工作,但不能作为脚本

    eval 'x = 3'
    puts x # throws an exception when run as a script
    => 3
    

    在 IRB 中工作并作为脚本

    x = 1
    eval 'x = 3'
    puts x
    => 3
    

    quote Matz

    局部变量应该在编译时确定,因此是局部的 在 eval'ed 字符串中首先定义的变量,只能从 其他经过评估的字符串。此外,它们在 Ruby2,这样这些变量就不会被外部访问。

    不同之处在于,在 IRB 中,一切 都在进行评估,因此它们都在同一个范围内。也就是说,您实际上是在 IRB 中执行此操作:

    eval 'x = 3'
    eval 'puts x'
    

    在 IRB 和脚本中都可以使用。

    【讨论】:

    • 我不知道 eval 在较低范围内运行。但是在主脚本体中定义 x 会导致变量通过引用传递给 eval 吗?
    • 是的,它的行为似乎很像这样:1.times {a = 3}; puts a; # NameError: undefined local variable or method 'a' for main:Objecta = 1; 1.times {a = 3}; puts a; # 3 从链接的线程来看,Matz 以这种方式工作是为了实现方便。
    • 那么,一个元编程新变量如何命名,这将在元编程读取部分之外(没有全局变量)? Ruby 不是让不可能成为可能的语言,而且优雅吗?
    • 也许行为改变了,现在我在 ruby​​ 2.2.6 上的 irb 0.9.6 不再运行“Works in IRB”示例
    【解决方案2】:

    因为您在 IRB 中定义了一个名为 machine 的方法或变量,而不是在您的 Ruby 脚本中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-13
      • 2020-07-23
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 2014-05-15
      • 1970-01-01
      相关资源
      最近更新 更多