我正在尝试逐行读取文件并将新字符串连接到每行的末尾。为了测试,我已经完成了这个:
(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
以使其不返回懒惰序列吗?
答案 0 :(得分:1)
take
功能在设计上是懒惰的,因此您可能必须使用first
,next
或nth
来实现所需的值,或者操作整个seq包含apply
,reduce
,vec
或into
等函数。
在您的情况下,您似乎正在尝试执行以下操作:
(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。