适用于Clojure lazy-eval

时间:2013-10-10 15:13:52

标签: clojure eval lazy-evaluation take

我正在尝试逐行读取文件并将新字符串连接到每行的末尾。为了测试,我已经完成了这个:

(defn read-file
[filename]
(with-open [rdr (clojure.java.io/reader filename)]
  (doall (line-seq rdr))))

(apply str ["asdfasdf" (doall (take 1 (read-file filename)))])

如果我只是在repl中评估(take 1 (read-file filename)),我会得到该文件的第一行。但是,当我尝试评估上面所做的事情时,我得到"asdfasdfclojure.lang.LazySeq@4be5d1db"

任何人都可以解释如何强制评估take以使其不返回懒惰序列吗?

1 个答案:

答案 0 :(得分:1)

take功能在设计上是懒惰的,因此您可能必须使用firstnextnth来实现所需的值,或者操作整个seq包含applyreducevecinto等函数。

在您的情况下,您似乎正在尝试执行以下操作:

(apply str ["asdfasdf" (apply str (take 1 (read-file filename)))])

或者:

(str "asdfasdf" (first (read-file filename)))


您还可以使用doall实现整个lazyseq。请记住,一个已实现的懒惰seq仍然是一个seq。

(realized? (take 1 (read-file filename))) ;; => false
(type (take 1 (read-file filename))) ;; => clojure.lang.LazySeq

(realized? (doall (take 1 (read-file filename)))) ;; => true
(type (doall (take 1 (read-file filename)))) ;; => clojure.lang.LazySeq


更好的选择是使用类似map之类的方式懒惰地应用转换,并从生成的seq中选择所需的值。 (与流处理一样。)

(first (map #(str "prefix" % "suffix")
             (read-file filename)))

注意: map很懒,所以它会返回一个未实现的LazySeq。