2017-10-10 13 views
3

Clojure에 Java의 try-with-resources 구조체가 있습니까?Clojure에서 리소스 사용 시도

그렇지 않은 경우 Clojure 코드에서이 관용구를 처리하는 일반적인 방법은 무엇입니까?

리소스를 안전하게 열고 닫을 수있게하는 Java 이전 버전의 관용구는 언어에 대한 try-with-resources에 대한 지원을 실제로 추가 할만큼 충분히 장황합니다. 표준 Clojure 라이브러리에서이 사용 사례에 대한 매크로를 찾을 수 없다는 것이 이상한 것처럼 보입니다.

Clojure 기반 프로젝트 저장소의 주류 (이 문제를 실제로 어떻게 처리하는지 보여주는 예제)가 매우 유용합니다.

답변

6

with-open을 사용하여 리소스를 심볼에 바인딩하고 제어 흐름이 블록을 떠난 후에 리소스가 닫혀 있는지 확인할 수 있습니다.

다음 예는 clojuredocs의 예제입니다.

(with-open [r (clojure.java.io/input-stream "myfile.txt")] 
    (loop [c (.read r)] 
     (when (not= c -1) 
     (print (char c)) 
     (recur (.read r))))) 

는 다음에 확장됩니다 : 당신은 let 블록이 try로 생성되는 것을 볼 수 있습니다

(let [r (clojure.java.io/input-stream "myfile.txt")] 
    (try 
    (loop [c (.read r)] 
     (when (not= c -1) 
     (print (char c)) 
     (recur (.read r)))) 
    (finally (.close r)))) 

- 전화 .close() 방법 finally.

+0

좋습니다. 나는 여전히'with-open' 주위에 또 다른'try' 폼을 추가해야만 리소스를 열거 나 사용할 때 던져지는 예외를 잡을 수 있습니다.하지만 try/catch 로직과는 별도로 열기/닫기 자동화를 처리하는 것은 아닙니다. 나쁜 것. Java 구조와 1 : 1의 동등성을 기대하고 있었지만 실제로 그렇게해야 할 이유는 없습니다. – DaoWen

+0

'(try ...)'블록 안에'(catch exceptions e ...)'와'(finally (.close r))'를 둘 수 있지만'with-resource' 매크로는 지원하지 않습니다 그것은 기본적으로 당신이 직접 작성해야합니다. – erdos

+0

@DaoWen 1 : 1 등가물입니다. 'try (Foo x = bar()) {...}'는'bar()'를 호출하는 동안 발생한 예외를 처리하지 않습니다. 어떻게 그럴 수 있니? 유효한'x'는'.close()'를 호출 할 범위에 없습니다. – amalloy

0

당신은 자바에 더 가깝게 뭔가를 할 수 있습니다. with-open 위에 매크로를 만듭니다. 다음과 같이 표시 될 수 있습니다.

(defmacro with-open+ [[var-name resource & clauses] & body] 
    (if (seq clauses) 
    `(try (with-open [~var-name ~resource] [email protected]) 
      [email protected]) 
    `(with-open [~var-name ~resource] [email protected]))) 

이렇게하면 바인딩 옆에 다른 절을 전달할 수 있습니다.

(with-open+ [x 111] 
    (println "body")) 

은 간단 with-open로 확장 :

(let* 
    [x 111] 
    (try (do (println "body")) (finally (. x clojure.core/close)))) 

추가 조항이 시도 - 캐치에 그것을 포장으로 이어질 때 :

(with-open+ [x 111 
      (catch RuntimeException ex (println ex)) 
      (finally (println "finally!"))] 
    (println "body")) 

여전히

(try 
    (let* 
    [x 111] 
    (try (do (println "body")) (finally (. x clojure.core/close)))) 
    (catch RuntimeException ex (println ex)) 
    (finally (println "finally!"))) 

그러나로 확장 꽤 의견이다. 에드 솔루션입니다.