2013-06-30 45 views
0

我已經閱讀了幾本關於Ruby的書,並且瞭解了Procs是如何創建和調用的。但是這些書中的例子是人爲和微不足道的。我想知道什麼時候使用Proc而不是使用傳統的方法來做同樣的事情?也許有人可以發佈一個不平凡的例子?何時在Ruby中使用Procs?

+1

你認爲什麼是「傳統的做同樣的事情」? –

+0

我想我的意思是調用一個我想在其中預先定義的代碼的方法,而不是將塊轉換爲Proc,然後調用Proc。 – mikeglaz

+0

proc/lambda在Ruby中隨處可見......就像每個地圖一樣。 – texasbruce

回答

1

在Ruby中,Proc是存儲稍後要在對象中運行的一小段代碼的好方法。塊不是對象,但它們可以很容易地轉換爲Procs。 Procs對很多事情都很有用。 Procs通常用於實現callbacks。我最近在編寫系統仿真時使用了Procs。每次我在模擬中調用step方法時,我都希望發生各種事情。我不希望模擬對象本身知道這些事情的細節;我只是想讓它調用我定義的回調函數。我可以通過定義一組自定義類或對象來完成同樣的事情,每個類都有一個call方法,但使用Procs確實更簡單。

class X 
    def initialize 
    @step_callbacks = [] 
    end 

    def every_step(&proc) 
    # If you print proc.class here, you can see it is a Proc 
    @step_callbacks << proc 
    end 

    def step 
    # ...perform the step... 
    @step_callbacks.each do |proc| 
     proc.call 
    end 
    end 
end 

x = X.new 

x.every_step do 
    # check some assertions about the state of the simulation 
end 

x.every_step do 
    # update a related simulation 
end 

x.step 
x.step 

我希望你不要認爲這個例子是人爲的。我確實用它來完成工作。此外,我使用相同的模式來處理我的Minecraft機器人中收到的數據包,as you can see here

回調是非常有用的,每當你想有一些對象調用一些代碼,但你不希望它確切地知道它調用了什麼代碼。 Procs是實現回調的簡單方法。

+0

這個問題是出於無知......爲什麼不把每個塊變成一個Proc到一個方法呢? – mikeglaz

+0

這將需要更多的代碼行,並要求您創建新的方法名稱。另外,它可能會要求您創建一個額外的對象來接收該方法調用。 –

0

Proc是一個對象,因此您可以創建包含它們的複雜對象。例如,您可以建立符合鍵指令的哈希:

object1 = { 
    :foo => ->{execute_foo_routine}, 
    :bar => ->{execute_bar_routine}, 
    ... 
} 
... 
object1[:foo].call # => execution 

注意,所有的信息都包括在object1。當你想要封裝所有必要的信息並使其獨立於外部代碼時,這很有用。 object1是便攜式的。

如果你想做的事,使用方法,那麼不是所有的信息可以在對象內部放,但方法需要被其他地方定義:

object2 = { 
    :foo => :foo_routine, 
    :bar => :bar_routine, 
    ... 
} 

def foo_routine 
    ... 
end 
def bar_routine 
    ... 
end 
... 
send(object2[:foo]) # => execution 

object2不會像object1便攜式。

+1

這並不能很好地展示特效。你的第一個例子使用'labmda' procs,你使用'send'的第二個例子根本不使用procs。另外,不要在'send'上使用'public_send'。 – naomik

+1

@naomik你誤解了我的答案。你提到的「第二個例子」是一個不使用procs的例子,與使用procs的例子比較。 – sawa