2011-06-15 37 views
15

我有一個臭方法,如:紅寶石「回報,除非無」成語

def search_record(*args)  
    record = expensive_operation_1(foo) 
    return record unless record.nil? 

    record = expensive_operation_2(foo, bar) 
    return record unless record.nil? 

    record = expensive_operation_3(baz) 
    return record unless record.nil? 

    record = expensive_operation_4(foo, baz) 
    return record unless record.nil? 
end 

是否有「呼叫,除非零返回結果」良好的紅寶石成語?

或者我應該只寫一個return_unless_nil(&blk)方法?

(請注意,ARG遊戲爲每個調用不同的,所以我不能只是簡單地在它們之間迭代)

+0

可以記錄爲'false',或者絕對是真實記錄還是零? – 2011-06-15 06:07:28

+0

「或者我應該寫一個'return_unless_nil(&blk)'方法?」哪個會從調用它的方法返回?我不認爲這是可能的。 – 2011-06-15 06:10:35

+0

我有約10分鐘的時間在學習紅寶石,但我很好奇你會怎麼寫一個方法來爲調用者返回一個值?至於一個潛在的答案,我覺得這是一個真正的答案,因爲我的紅寶石曝光非常有限......你可以在紅寶石中使用類似的東西嗎? 'return(record = expensive_op(foo))除非record.nil?'不知道這對你是否有點臭? – 2011-06-15 06:13:09

回答

20

你關心nilfalse這裏有什麼區別?如果你只關心每一個方法的返回值是否爲「falsy」,那麼這是做的相當Rubyish方式:

def search_record(*args)  
    expensive_operation_1(foo)  || 
    expensive_operation_2(foo, bar) || 
    expensive_operation_3(baz)  || 
    expensive_operation_4(foo, baz) 
end 

如果你不熟悉這個成語,它可以解釋正是如此:紅寶石,如同大多數語言一樣,"short circuits"或比較,意思是如果第一個操作數的計算結果爲「truey」,則不會費心去評估第二個操作數(即如果expensive_operation_1返回nilfalse以外的東西,它將不會呼叫expensive_operation_2) ,因爲它已經知道布爾運算的結果是真的。

Ruby所做的另一個有用的事情是,不是從布爾操作返回truefalse它只是返回它評估的最後一個操作數。因此,在這種情況下,如果expensive_operation_1返回nil,則它將調用expensive_operation_2,如果返回值(不是僞造的),則整個表達式將僅計算該值。

最後,我們可以鏈接這些布爾值,實際上,它將返回第一個非謬誤的操作數的結果,並且不會評估後面的操作數。如果所有的操作數評估爲虛假,它將返回最終操作數(我們知道這是操作數是虛的,在您的情況下,可能是nil)。

+0

要擴展Jordan的相當簡潔的答案:布爾運算符短路(如果不需要右側,則只計算左側)並返回滿足運算符的值。 – Chuck 2011-06-15 06:13:12

+0

謝謝查克。當你評論時,我正忙於擴展我的答案。 :) – 2011-06-15 06:14:17

+0

需要注意的是,「你關心零與假之間的區別」的確很重要。如果這些函數中的任何一個返回一個布爾值,這段代碼將不會執行。不幸的是,OP已經走了。 – tokland 2011-06-15 11:04:09

2

補充喬丹的答案:讓我們想象這些函數可能會返回一個布爾值(不可能用於搜索函數,但無論如何)並且||不起作用。然後我們可以使用討論的抽象here

expensive_operation_1(foo).or_if(:nil?) do 
    expensive_operation_2(foo).or_if(:nil?) do 
    expensive_operation_3(foo).or_if(:nil?) do 
     expensive_operation_4(foo) 
    end 
    end 
end 
+0

Object#or_if是一個值得記住的有趣成語。謝謝! – pithyless 2011-06-15 18:00:39