Clojure是否具有Java try-with-resources构造的等价物?
如果没有,在Clojure代码中处理这个习惯用法的正常方法是什么?
用于安全打开和关闭资源的Java-7之前的习惯用语非常冗长,以至于它们实际上增加了对该语言的try-with-resources的支持。我觉得很难在标准的Clojure库中找到这个用例的宏。
基于Clojure的主流项目存储库的一个示例 - 显示如何在实践中处理此问题 - 将非常有用。
答案 0 :(得分:9)
您可以使用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 [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))))
您可以看到let
块是使用try
- finally
创建的.close()
方法。
答案 1 :(得分:0)
你可以做一些更接近java的事情,在with-open
之上构建一些宏。它看起来像这样:
(defmacro with-open+ [[var-name resource & clauses] & body]
(if (seq clauses)
`(try (with-open [~var-name ~resource] ~@body)
~@clauses)
`(with-open [~var-name ~resource] ~@body)))
因此您可以在绑定旁边传递其他条款。
(with-open+ [x 111]
(println "body"))
扩展为简单with-open
:
(let*
[x 111]
(try (do (println "body")) (finally (. x clojure.core/close))))
虽然附加条款导致将其包装在try-catch中:
(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!")))
但它仍然是一个固执己见的解决方案。