2014-01-18 65 views
0

以下工作在REPL中,以防數據庫關閉時我將地圖返回。如何有效捕捉不同功能的相同異常?

(try 
(insert-table "db" "table" {:id 1 :text "text"}) 
(catch Exception e {:err "can't connect to database"})) 

雖然我可以編寫一個函數,它需要一個數據庫操作並用(try)包裝它。

(defn catch-db-connection-errors 
    [db_operation] 
    (try 
    (db_operation) 
    (catch Exception e {:err "can't connect to database"}))) 

雖然沒有發現異常。我可能只是忽略了一些非常簡單的...

回答

3

問題在於,在函數被調用之前,您將傳入的表單作爲參數(例如(insert-table "db" "table" {:id 1 :text "text"}))進行求值,並將結果值傳遞給該函數。要使用另一個示例,如果您編寫(println (+ 1 1)),Clojure將首先評估(+ 1 1)以獲得2,然後將調用(println 2)。因此,如果在您的數據庫代碼中引發異常,則會在調用catch-db-connection-errors函數之前,因此超出try樣式。

你想要的是一個宏,幸好Clojure非常擅長。

(defmacro catch-db-connection-errors [& db-operations] 
    `(try 
    [email protected] 
    (catch Exception e {:err "can't connect to database"}))) 

這允許你傳入你想要的許多數據庫處理表單並將它們包裝在你的try-catch對中。

(順便說一句,你可能想趕上的東西一點點比異常更具體的,否則你可能最終會趕上你不打算做一個例外,但當然是題外話這裏的。)

+0

謝謝查克爲宏偉的解釋和宏觀。是的,好點,實際上我想在這裏捕捉所有與db操作有關的異常,不要讓它冒泡到更高層。另一方面,我可能只有幾個例子,並根據實際的異常類型更改返回的字符串。再次感謝你! – Istvan