Ruby Eval ведет себя по-разному в IRB по сравнению с файлом - PullRequest
4 голосов
/ 03 апреля 2009

Этот код работает в 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)

Может кто-нибудь объяснить, почему?

Ответы [ 2 ]

12 голосов
/ 03 апреля 2009

Это потому, что переменная 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

К Цитата Матц :

локальные переменные должны быть определены во время компиляции, таким образом, локальные переменные, определенные первыми в строке eval'ed, доступны только из другие eval'ed строки. Кроме того, они будут более эфемерными в Ruby2, так что эти переменные не будут доступны извне.

Разница в том, что в IRB все оценивается как единое целое, поэтому все в одной области. То есть, по сути, вы делаете это в IRB:

eval 'x = 3'
eval 'puts x'

, который работает как в IRB, так и в виде скрипта.

0 голосов
/ 03 апреля 2009

Поскольку вы определяете метод или переменную с именем machine в IRB, но не в своем скрипте Ruby.

...