2011-09-09 19 views
1

Ruby 1.9でeval()を使用して、ルビコードをインタラクティブな方法でテストしたいと思います。ずっと前(Ruby 1.4を中心に)私はこの機能を提供するインターネット上できちんとしたスクリプトを見つけました。ここでは単純化して低減されたバージョン:原因eval()の変更セマンティクスにただしていないもう1.9で、Ruby 1.9でeval()を使用してRubyコードスニペットをテストする

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

このスクリプトは、Rubyの1.8まで正常に動作します:

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 

は、私のような何かをすることができました。今私は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の2番目の引数として送信することもできます。

def get_a_binding 
    x = 42 
    return binding 
end 

x = 50 
scope = get_a_binding 
eval("print x", scope) #=> prints 42 
関連する問題