2012-01-26 7 views
3

ローカル変数と定数の両方を定義するために、文字列のevalを実行します。 私は別の名前空間でこれをやりたい私は局所変数 でこれを行うことができますが、定数ではできません。あるバインディング/名前空間で定義された定数が別のものによって見られないように、NameSpacesモジュールを 以下に変更する方法はありますか?一見のためRubyバインディング - ローカル変数と定数のスコープ

# Example run under ruby 1.9.1 
module NameSpaces 
    def self.namespace(namespace) 
    return binding 
    end 
end 

b1 = NameSpaces.namespace("b1") 
b2 = NameSpaces.namespace("b2") 

# Set a 'x', then check to make sure its still set in the scope of 'b1' 
puts b1.eval("x = 1") # => 1 
puts b1.eval("x")  # => 1 

# Check to make sure 'x' is NOT set in the scope of 'b2' 
begin 
    puts b2.eval("x") # NameError exception expected here 
rescue Exception => e 
    puts e.to_s  # => undefined local variable or method `x' 
        # for NameSpaces:Module (THIS IS AS EXPECTED.) 
end 

# Set constant 'C' and do the same checks 
puts b1.eval("C = 1") # => 1 
puts b1.eval("C")  # => 1 

# Check to make sure 'C' is NOT set in the scope of 'b2' 
begin 
    puts b2.eval("C") # (I DON'T GET AN EXCEPTION. NOT AS I HAD HOPED FOR.) 
rescue Exception => e 
    puts e.to_s 
end 

本当にありがとうございました。私は非常に固執しています。

答えて

5

あなたが観察している動作は正常です。 NameSpaces.namespaceの呼び出しの範囲でC = 1を実行すると、定数 "C"はNameSpacesに定義されます。 NameSpaces::Cを試して確認できます。

欲しい効果を得るには、匿名モジュールのバインディングを使用する必要があります。 (グローバルスコープIE)オブジェクトで定義されている任意の定数はevalに渡されたコード内で使用可能になること

namespace1 = Module.new.class_eval("binding") 
namespace2 = Module.new.class_eval("binding") 
namespace1.eval("C = 1") 
namespace1.eval("C") 
=> 1 
namespace2.eval("C") 
NameError: uninitialized constant #<Module:0xf09180>::C 

注、およびそのような定数の値を評価コードに変更された場合、これを試します変更は世界的に見ることができます!

(と名前を付けることによって、オブジェクトに定義されたあなたはObjectから継承しないBasicObjectのコンテキストでコード、評価されたコードを評価する場合でもできまだアクセス定数「::」)

+0

ありがとうアレックス。それは有益です。私は何か不足しているかもしれませんが、私はこのタイプの評価がローカル変数のための最初のテストケースに失敗したと思います。私はこのメソッドを使うと、プログラムに渡された式を解析して、特定の形式のevalを決定しなければならないと思います。私が望んでいるプログラムは、エンドユーザーが入力したすべての入力を受け取り、それを式として解析するが、プログラムのものではなくユーザー自身の名前空間で解析する。 – dinman2022

+0

@ dinman2022、実際には、ローカル変数でテストしました。 –

+0

私は地元の人々が通話の範囲外になることを望んでいません。例:\ 'MyClassクラス がDEF @spaces = {} self.namespace = 'デフォルト' 端DEFネームスペース=(ID) @namespace = @ spaces.has_keyを初期化(ID)? @spaces [ID]:Module.new エンド デフdo_me(EXP) 場合EXP =〜/ ^名前空間/ self.namespace = exp.split [1] 他 namespace.class_eval @(EXP) 終了L | | 端端 入力=%のQ C = MyClass.new input.each_line {{ X = 1 X#=>ここに 名前空間new_oneダイ X位 を失敗し} はc.do_me(L) レスキュー例外を置き始める=> E を置くE 端} ' – dinman2022

関連する問題