2011-09-09 91 views
1

我想在Ruby 1.9中使用eval()以交互方式測試一小段ruby代碼。很久以前(圍繞Ruby 1.4),我在互聯網上找到了一個提供此功能的整潔腳本。這裏被簡化和降低版本:在Ruby 1.9中使用eval()測試Ruby代碼片段

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,在1.9然而,不再因eval()改變的語義。現在我無法再使用str等局部變量。相反,我得到以下明顯的信息:

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

有沒有辦法修復或繞過eval()的這種行爲?我已經閱讀了關於綁定的一些信息,但我不確定在這裏如何做到這一點。

當然有irb但在該工具中,我不能使用像"abc#{var}def"中的磅符號。如果我嘗試,然後irb評論整條線。

+0

'「abc#{var} def」'在我的irb中工作。 – Dogbert

回答

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