2014-01-18 2 views
0

다음은 REPL에서 작동합니다. 데이터베이스가 다운 된 경우 맵을 다시 얻습니다.다른 함수에 대해 동일한 예외를 효율적으로 잡는 방법은 무엇입니까?

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

DB 작업을 수행하고 (시도)로 감싸는 함수를 작성할 수는 있지만.

(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)을 호출합니다. 따라서 DB 코드에서 예외가 발생하면 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 연산과 관련된 모든 예외를 catch하고 싶습니다. 상위 계층으로 버블 링하지 마십시오. 다른면에서는 예외가 거의 없을 수도 있고 실제 예외 유형에 따라 반환 된 문자열을 변경할 수도 있습니다. 다시 감사합니다! – Istvan

관련 문제