1

我想eval()在 Ruby 1.9 中以交互方式测试一小段 ruby​​ 代码。很久以前(大约 Ruby 1.4)我在互联网上发现了一个提供此功能的简洁脚本。这是简化和简化的版本:

line = ''
$stdout.sync = true
print "ruby> "
while true
    input = gets
    if input
        line = input 
    else
        break if line == ''
    end
    begin
        print eval(line).inspect, "\n"
    rescue ScriptError, StandardError
        $! = 'exception raised' unless $!
        print "ERROR: ", $!, "\n"
    end
    break if not input
    line = ''
    print "ruby> "
end

我能够做类似的事情:

ruby> str = "a:b:c"
"a:b:c"
ruby> str.split /:/
["a", "b", "c"]
ruby>

该脚本在 Ruby 1.8 之前可以正常工作,但由于eval(). 现在我不能再制作局部变量str了。相反,我收到以下明显消息:

ERROR: undefined local variable or method `str' for main:Object

有没有办法修复或绕过这种行为eval()?我读过一些关于绑定的东西,但我不知道如何在这里做。

当然有,irb但在那个工具中我不能像 in 那样使用井号"abc#{var}def"。如果我尝试然后irb注释掉整行。

4

1 回答 1

4

工作代码:

$stdout.sync = true
while true
  print "ruby> "
  input = gets
  break unless input
  begin
    p eval(input, TOPLEVEL_BINDING)
  rescue ScriptError, StandardError
    puts "ERROR: #{$! || "exception raised"}"
  end
end

我更改了代码中的许多内容以使其干净,但重点是eval. 它正在begin块内执行。由 定义的所有局部变量eval都在块内创建,并在每次迭代后结束begin时被销毁。begin常量TOPLEVEL_BINDING返回顶层的范围(一切之外)。它使 eval 在不会被破坏的地方执行代码(直到程序结束)。您还可以使用该方法获取任何地方的范围,binding并将其作为eval.

def get_a_binding
  x = 42
  return binding
end

x = 50
scope = get_a_binding
eval("print x", scope) #=> prints 42
于 2011-09-09T13:50:52.780 回答