【问题标题】:Why is line-seq returning clojure.lang.Cons instead of clojure.lang.LazySeq?为什么 line-seq 返回 clojure.lang.Cons 而不是 clojure.lang.LazySeq?
【发布时间】:2013-02-17 10:16:28
【问题描述】:

根据 line-seq (http://clojuredocs.org/clojure_core/clojure.core/line-seq) 的 ClojureDocs 条目和 Stack 问题 (In Clojure 1.3, How to read and write a file) 的公认答案,line-seq 在传递 java.io.BufferedReader 时应该返回惰性序列。

但是,当我在 REPL 中对此进行测试时,该类型被列为 clojure.lang.Cons。请看下面的代码:

=> (ns stack-question
     (:require [clojure.java.io :as io]))
nil
=> (type (line-seq (io/reader "test-file.txt")))
clojure.lang.Cons
=> (type (lazy-seq (line-seq (io/reader "test-file.txt"))))
clojure.lang.LazySeq

在惰性序列调用中结束 line-seq 调用会产生惰性序列,但根据文档,这不是必需的:无论如何,line-seq 都应该返回惰性序列。

注意: 在 REPL(我正在使用 nrepl)内部,似乎懒惰的 seq 被完全实现了,所以我认为这可能只是 REPL 的一个怪癖;但是,当我使用 Speclj 对其进行测试时,也存在同样的问题。另外,我不认为实现惰性序列与正在发生的事情有关。

编辑: 所以在mobyte的回答说cons的尾部有一个lazy seq之后我去查看源代码......

1   (defn line-seq
2     "Returns the lines of text from rdr as a lazy sequence of strings.
3     rdr must implement java.io.BufferedReader."
4     {:added "1.0"}
5     [^java.io.BufferedReader rdr]
6     (when-let [line (.readLine rdr)]
7       (cons line (lazy-seq (line-seq rdr)))))

对 cons 的调用可以解释为什么 line-seq 的返回值的类型是 clojure.lang.Cons。

【问题讨论】:

    标签: file-io clojure lazy-sequences cons


    【解决方案1】:

    您不需要“包装”输出Cons,因为它已经将惰性序列作为“尾巴”:

    (type (line-seq (io/reader "test-file.txt")))
    => clojure.lang.Cons
    
    (type (rest (line-seq (io/reader "test-file.txt"))))
    => clojure.lang.LazySeq
    
    (type (cons 'a (rest (line-seq (io/reader "test-file.txt")))))
    => clojure.lang.Cons
    

    编辑。

    注意:在 REPL(我正在使用 nrepl)内部,似乎惰性 seqs 完全实现

    不正确。你可以测试一下:

    (with-open [r (io/reader "test-file.txt")] (line-seq r))
    => IOException Stream closed  java.io.BufferedReader.ensureOpen (BufferedReader.java:97)
    

    这是因为line-seq 返回的lazy-seq 没有完全实现,而reader 在repl 稍后尝试实现结果打印时已经关闭。但是如果你明确地意识到它会给出正常的结果,没有任何例外:

    (with-open [r (io/reader "/home/mobyte/2")] (doall (line-seq r)))
    => ...  output ...
    

    【讨论】:

    • 所以我想在 REPL 中输入 (line-seq my-buffered-reader) 并完全打印出来意味着惰性序列仅针对打印步骤进行评估,但直到那时才真正评估?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2015-11-02
    • 2021-09-13
    • 2017-06-30
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多