2012-02-12 34 views
2

我想寫一個方法(define_variables),它可以得到block並使用它定義的變量。可能嗎?例如,我想得到5輸出:是否可以在方法中訪問塊的作用域?

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

A::define_variables do 
    a = 5 
end 

也許有一些技巧與eval,但還沒有找到任何人。

+3

這是什麼實際使用情況?這對我來說似乎倒退了。 – 2012-02-12 02:42:34

+1

如果您想利用在已傳遞的塊內進行的一些計算,最好的辦法是從該塊返回一些內容並對其進行處理。依賴傳遞的proc中的局部變量的命名沒有多大意義。什麼是保證某人使用「a」作爲變量?當你不想要的時候,你會如何防止任意proc跺跺自己的變量? – 2012-02-12 04:24:39

+0

我想爲簡單的控制檯遊戲製作一個'GameWorld'模塊,這個模塊有'load'和'run'方法。 load方法加載game_objects並將它們存儲在數組中,'run'來描述它們之間的一些交互。在GameWorld的範圍中,我可以訪問game_objects數組並輸出一些信息(健康狀況,分數等)。只是爲了「對稱」和學習的目的,我試圖用這兩種方法使用塊。現在,我將對象直接加載到模塊的常量「game_objects」中。無論如何,非常感謝您的幫助,現在我們越來越清楚範圍和區塊的工作方式。 – evfwcqcg 2012-02-12 04:54:08

回答

5

總之,沒有。在你調用yield之後,那些在塊中定義的變量是不見了(我們將會看到),除了返回的內容 - 這就是範圍的工作原理。在你的例子中,5仍然在那裏,它是由塊返回,因此puts yield將打印5。使用這個,你可以從塊{:a => 5}返回一個散列,然後以這種方式訪問​​多個「變量」。在Ruby 1.8(在IRb only),你可以這樣做:

eval "a = 5" 
a # => 5 

雖然我不知道塊的反正eval內容。無論如何,in Ruby 1.9 the scope of eval was isolated,這會給你一個NameError。您可以在Binding的範圍內做一個eval雖然:

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

foo do 
    a = 5 
    binding 
end # => 7 

在我看來,你試圖做的是模仿宏在Ruby中,這僅僅是不可能的(at least not pure Ruby),和我勸阻使用上面提到的任何「解決方法」。

2

一致認爲這是一個倒退,安德魯的解釋是正確的。如果你的使用情況是定義的變量,但是,已經有class_variable_setinstance_variable_set方法,爲了這個,是偉大的:

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 

以上是你越已經發布,而如何將代碼內工作的例子比推薦。

+0

用實例/類變量繞過整個範圍問題肯定會讓'')''更容易推理。 – 2012-02-12 03:10:09

+0

我試圖看看我可以用給定的代碼來完成工作。看着這很聰明。 – ericraio 2012-02-12 03:19:31

相關問題