2011-05-02 68 views
4

我最近購買了這本書七週七種語言,並一直在閱讀關於Ruby的一章。在其中引入了塊(第40頁)段,代碼樣本中給出,它說明的有條件執行的東西爲目的使用的塊:你如何使用Ruby塊來有條件地執行某些事情?

in_case_of_emergency do 
    use_credit_card 
    panic 
end 

def in_case_of_emergency 
    yield if emergency? 
end 

此代碼沒有多大意義,我,和本書沒有提供太多的解釋。我想知道你們中的一位Ruby大師會不會介意幫助我解決這個問題。

你怎麼能有一個塊和同名的函數?你如何定義「緊急?」我甚至無法在IRB中創建塊,但不會抱怨:

NoMethodError: undefined method `in_case_of_emergency' for main:Object 
    from (irb):1 
    from :0 

而您將如何調用此代碼來演示它的工作原理?謝謝!

回答

10

首先:兩個順序錯誤。您首先需要定義in_case_of_emergency

第二:你沒有命名塊;因此,有兩個名爲in_case_of_emergency的東西是不正確的。一個是功能定義,而第二個是該功能的功能調用

所以,一步一步:

def emergency? 
    return rand(2) == 0 
end 

比方說,你有這樣的函數,返回true一半的時間,並false一半的時間,隨機。 (男孩,這是一個很大的緊急!)然後:

def in_case_of_emergency 
    yield if emergency? 
end 

這定義了一個名爲in_case_of_emergency功能。當被調用時,它執行yield if emergency?,它是由條件if修改的語句yield。這是句法糖

if emergency?() 
    yield 
end 

請注意,Ruby不需要用於函數調用的括號,因此我們可以放棄它們;如果if中只有一條語句,則可以將它寫在上面的同一行(不需要end)。

接下來,我們有一個函數調用:

in_case_of_emergency do 
    use_credit_card 
    panic 
end 

這就要求我們剛剛定義,in_case_of_emergency功能,傳遞一個塊來執行。這些是將由yield執行的兩條語句(use_credit_card,panic) - 但僅當emergency?的計算結果爲true

現在這樣做更有意義嗎?

+0

阿馬丹是對的。 @Steve你確定這本書按照這個順序給出了代碼嗎? – sawa 2011-05-02 05:16:25

+0

+1,它應該按照Amadan提到的順序進行 – 2011-05-02 05:19:14

+0

是的,這是書中給出的順序。 – 2011-05-02 05:58:47

2

這是簡單的,那就是方法:

def in_case_of_emergency 
    yield if emergency? 
end 

,這是調用你的方法:

in_case_of_emergency do 
    use_credit_card 
    panic 
end 

何在

do 
    use_credit_card 
    panic 
end 

一種說法。 Ruby方法可以隱式地將塊作爲參數。會發生什麼, yield將執行您提供的塊。在你的情況下,yield if emergency?表示「如果條件滿足,則執行提供的程序段」。

1

添加到其他答案,如果您放棄yield關鍵字並將其視爲實際存在的Procs方法,可能會更容易理解塊。

# for testing purposes, let's always have `emergency?` return `true` 
def emergency? 
    true 
end 

def in_case_of_emergency(&block) 
    block.call if emergency? 
end 

in_case_of_emergency do 
    puts "AHH! Emergency! Help!", "Seriously, I'm freaking out!" 
end 

看看有多容易意識到塊實際上是一個參數?

相關問題