Clojure:从输入流创建字节 block 的惰性序列

标签 clojure inputstream lazy-sequences

给定一个输入流,我想以字节数组( block )的形式创建一个惰性数据序列。这是我的尝试:

(defn- read-or-nil [stream]
  (let [buf (byte-array 2)]
    (when-not (= -1 (.read stream buf))
      buf)))

(defn byte-chunk-seq [stream]
  (cons (read-or-nil stream) (lazy-seq (byte-chunk-seq stream))))

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")]                                                                                                                                                                                         
  (take 2 (byte-chunk-seq rdr))) 

在最后一个语句中,我正在测试代码,我得到:

IOException 流已关闭 java.io.FileInputStream.readBytes (FileInputStream.java:-2)

如果我将语句更改为 take 1 那么它会返回正常,但这对我没有多大帮助。有谁知道为什么这行不通?

最佳答案

有几个问题。

首先,您的惰性序列并不完全正确。函数的整个主体应该包裹在lazy-seq中,并且应该传入cons来继续序列,或者传递nil来终止序列。

(defn byte-chunk-seq [stream]
  (lazy-seq (if-let [buf (read-or-nil stream)]
              (cons buf (byte-chunk-seq stream))
              nil)))

其次,take也是懒惰的。因此,直到 with-open 关闭流之后,惰性序列才会实现。您可以通过在惰性序列周围包装 doall 来避免此错误,以在流关闭之前实现它。

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")]
  (doall (take 2 (byte-chunk-seq rdr))))

关于Clojure:从输入流创建字节 block 的惰性序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17376269/

相关文章:

clojure - 如何在 Clojure 映射中排序键?理想情况下,根据键向量对它们进行排序

macros - 从 http ://lisperati. planvita.com/actions.html 了解游戏 Action clojure 宏的嵌套引号

java - Monad 和装饰器模式

Java:哪个具有更好的性能 - 将流推送到字符串?

Scheme 中的流 - 通过方案中的流映射定义整数

javascript - 如何在 typescript 中生成延迟迭代的东西

clojure - 在 Clojure 代码中嵌入任意对象

Java OutputStream 跳过(偏移量)

Java文件加密,无法让它接受文件输入

rust - Rust 中的惰性序列生成