2010-01-07 33 views
10

我真的沒有看到這些理智的使用。已經有rescueraise,那麼爲什麼需要throwcatch?看起來他們應該被用來跳出深厚的嵌套,但這只是聞起來像一個轉到我身上。有沒有任何好的,乾淨的使用這些例子?在Ruby中,catch和throw哪裏有用?

回答

6

注意:看起來有幾件事情隨着1.9的抓/拋出現了變化。這個答案適用於Ruby 1.9。

一個很大的區別是,你可以throw任何東西,不只是從StandardError派生的東西,不像raise。這樣的愚蠢是合法的,例如:

throw Customer.new 

但它不是很有意義。但你不能這樣做:

irb(main):003:0> raise Customer.new 
TypeError: exception class/object expected 
    from (irb):3:in `raise' 
    from (irb):3 
    from /usr/local/bin/irb:12:in `<main>' 
+0

該示例對於救援/加薪也是合法的。它只是說「救援條款所需的班級或模塊」。 – 2010-01-07 04:18:38

+0

另外,它告訴我,你只能捕捉/拋出一個符號。 – 2010-01-07 04:20:26

+0

@jleedev»你正在運行哪個版本的Ruby? [編輯:哎呀,我誤解了你說的話。我嚴重錯誤地說最後一句話,會解決。] – 2010-01-07 04:21:29

2

它基本上是一個goto,略微更類似於call/cc,除了控制流是通過名稱而不是顯式地作爲參數隱式連接的。拋出/捕獲和提升/救援之間的區別在於前者旨在用於控制流而不是僅僅出現異常情況,並且不會浪費時間放置堆棧跟蹤。

Sinatra對HTTP錯誤代碼使用throw/catch,其中處理程序可以使用throw以結構化方式將控制權交給Sinatra庫。其他類型的HTTP框架使用異常,或通過返回不同類別的響應,但是這使得Sinatra(例如)在捕獲它之後嘗試另一個請求處理程序。

1

兩者之間的區別在於,你只能'提升'例外,但可以拋出任何東西(1.9)。除此之外,它們應該是可以互換的,也就是說,應該可以相互重寫,就像@ john-feminella給出的例子一樣。

5

他們可以在通過傳遞控制了DSL的,而不需要複雜的情況下/簡化了最終用戶的DSL真正有用的if語句

我有一個Ruby應用程序,它允許用戶通過其擴展內部DSL。 DSL中的一些功能需要將控制返回到我的應用程序的特定部分。我們舉一個簡單的例子。假設用戶正在制定有關日期

if today is a holiday then 
    do nothing 
end 

week_of_year = today.week.number 

if week_of_year < 10 then 

... 

do nothing位觸發其通過控制出exec語句的遙,還給我一個簡單的擴展。

在某些情況下,我們希望它退出並將控制權交還給我的應用程序,而不是繼續執行DSL。現在,您可以讓用戶使用大量嵌入式if語句,並讓DSL自然結束,但這只是掩蓋了邏輯想要說的內容。

扔真的是一個'被認爲是危險的'goto,但該死的有時他們是最好的解決方案。

相關問題