4

此代码适用于 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)

谁能解释为什么?

4

2 回答 2

12

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

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

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

在 IRB 和脚本中工作

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

引用 Matz 的话:

局部变量应在编译时确定,因此首先在 eval'ed 字符串中定义的局部变量只能从其他 eval'ed 字符串访问。此外,它们在 Ruby2 中会更加短暂,因此这些变量不会被外部访问。

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

eval 'x = 3'
eval 'puts x'

它既适用于 IRB,也适用于脚本。

于 2009-04-03T18:46:22.553 回答
0

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

于 2009-04-03T18:08:42.410 回答