2012-02-12 4 views
2

私はblockを得ることができ、そこに定義された変数を使用する方法(define_variables)を書きたいと思います。出来ますか?例えば、私は5インチの出力を得たいと思っています。メソッドのブロックのスコープにアクセスできますか?

module A 
    def self.define_variables 
    yield 
    puts a # not 5 :(
    end 
end 

A::define_variables do 
    a = 5 
end 

多分evalといくつかの秘訣がありますが、まだ誰も見つかりませんでした。

+3

実際の使用例は何ですか?それは私にとってはかなり後ろにあるようです。 –

+1

渡されたブロック内で行われた計算を利用したい場合は、そのブロックから何かを返して何かを行うことが最善の方法です。渡されるproc内のローカル変数の命名に頼るのは大変意味がありません。誰かが "a"を変数として使用することを保証するにはどうすればよいですか?あなたが望んでいないときに、任意のprocが独自の変数をストンプするのをどのように防ぎますか? –

+0

私は単純なコンソールゲームのための 'GameWorld'モジュールを作ろうとしていました。このモジュールは' load'と 'run'メソッドを持っています。 loadメソッドを使用してgame_objectsをロードして配列に格納し、 'run'を使用してそれらの間の相互作用を記述します。 GameWorldのスコープでは、game_objects配列にアクセスしていくつかの情報(健康、スコアなど)を出力できます。 「対称性」と学習目的のために、私は両方の方法でブロックを使用しようとしていました。今は、オブジェクトを 'game_objects'というモジュールの定数に直接ロードします。とにかく、助けてくれてありがとう、スコープとブロックがどのように機能するかがはっきりしています。 – evfwcqcg

答えて

5

要するに、 yieldを呼び出した後、が返されます(返されるものを除き、)。返されるものを除き、それはスコープの仕組みです。あなたの例では、5はまだそれがブロックによって返されているので、puts yield5を印刷します。これを使用すると、ブロック{:a => 5}からハッシュを返し、そのように複数の「変数」にアクセスできます。 (IRb only中)のRuby 1.8では、あなたが行うことができます。

eval "a = 5" 
a # => 5 

を私はevalにとにかくのブロックの内容を知らないけれども。それにもかかわらず、in Ruby 1.9 the scope of eval was isolatedとこれはあなたにNameErrorを与えるでしょう。

def foo 
    b = yield 
    eval(a, b) + 2 
end 

foo do 
    a = 5 
    binding 
end # => 7 

あなたが何をしようとしていること(at least not pure Rubyを)だけでは不可能であるルビー、中にマクロをエミュレートしているように私には思える、と私は落胆:あなたはしかしBindingのコンテキスト内evalを行うことができます上記の "回避策"の使用。

2

これは少し後であり、Andrewの説明は正しいと約束しました。

module A 
    def self.define_variables(vars = {}) 
    vars.each { |n, v| class_variable_set n, v } 
    puts @@a 
    end 
end 

A::define_variables :@@a => 5 

上記のあなたではなく投稿したそれは、コード内で動作する方法の例の詳細です:ご使用の場合は、変数を定義している場合は、しかし、このために素晴らしいですclass_variable_setinstance_variable_set方法が既に存在しています推薦よりも。

+0

スコープの問題全体をインスタンス/クラス変数でバイパスすることは、 ':)'についてこれをはるかに容易にします。 –

+0

私はそれを動作させるために与えられたコードを使って何ができるかを見てみました。これを見てもかなり賢かったです。 – ericraio

関連する問題