如何在Clojure中实现可关闭的lazy-seq?最优方案探讨
实现带Closeable特性的Clojure惰性序列
问题描述
我尝试在Clojure中创建一个同时具备Closeable特性的lazy-seq,请问最简洁的实现方式是什么?预期使用示例如下(仅为其中一种,还存在更多可关闭惰性序列的使用场景):
(with-open [lines (file-lines-seq file)] (consume (map do-stuff-to-line lines)))
该用法等价于:
(with-open [reader io/reader file] (consume (map do-stuff-to-line (line-seq reader))))
简洁实现方案
直接通过reify将惰性序列与Closeable接口绑定,核心实现如下:
(require '[clojure.java.io :as io]) (defn file-lines-seq [file] (let [reader (io/reader file) lines (line-seq reader)] (reify clojure.lang.Seqable (seq [_] lines) java.io.Closeable (close [_] (.close reader)))))
实现说明
- 先初始化文件读取器
reader,并生成对应的惰性行序列line-seq - 通过
reify实现两个关键接口:Seqable:让这个对象可以被当作普通序列使用,支持map、consume等序列操作Closeable:提供close方法,用于关闭底层的文件读取器
with-open会自动调用close方法,无论代码正常执行还是抛出异常,都能确保资源被正确释放- 保持了
line-seq的惰性特性,只有在消费序列时才会实际读取文件内容
内容的提问来源于stack exchange,提问作者Ionut Bilica
相关产品推荐
相关产品推荐

