Clojure 将文件行的延迟序列传递给函数
为什么这段代码不起作用Clojure 将文件行的延迟序列传递给函数,clojure,Clojure,为什么这段代码不起作用 (defn with-file [fname fn] (with-open [r (reader fname)] (fn (line-seq r)))) (with-file "data/input_d2" (fn [x] (map count x))) 我正在打开一个文件,当它打开时,我正在向提供的函数传递一个延迟的行序列 (defn with-file [fname fn] (with-open [r (reader fname
(defn with-file [fname fn]
(with-open [r (reader fname)]
(fn (line-seq r))))
(with-file "data/input_d2" (fn [x] (map count x)))
我正在打开一个文件,当它打开时,我正在向提供的函数传递一个延迟的行序列
(defn with-file [fname fn]
(with-open [r (reader fname)]
(doall (fn (line-seq r)))))
(with-file "data/input_d2" (fn [x] (map count x)))
我得到的错误是:
Error printing return value (IOException) at java.io.BufferedReader/ensureOpen (BufferedReader.java:122).
Stream closed
我刚想出来。
因为行seq是惰性的,所以它上的所有操作都返回惰性seq。
因此,调用with file函数会返回一个lazy seq,REPL稍后会尝试对其求值,但此时文件已经关闭
因此,我们需要强制计算从传递的函数返回的内容
(defn with-file [fname fn]
(with-open [r (reader fname)]
(doall (fn (line-seq r)))))
(with-file "data/input_d2" (fn [x] (map count x)))
我刚想出来。
因为行seq是惰性的,所以它上的所有操作都返回惰性seq。
因此,调用with file函数会返回一个lazy seq,REPL稍后会尝试对其求值,但此时文件已经关闭
因此,我们需要强制计算从传递的函数返回的内容
(defn with-file [fname fn]
(with-open [r (reader fname)]
(doall (fn (line-seq r)))))
(with-file "data/input_d2" (fn [x] (map count x)))
另外,请澄清参数名称,如
fn
=>f
或fn
。另外,我会直接用doall
或vec
来包装行序列
,比如:(f(vec(lineseq r)))
。直接用doal来包装行序列不会破坏使用惰性序列的整个目的吗?它将全部加载到内存中,但对于大多数目的来说,这并没有什么区别。除非确实需要延迟处理管道,否则我喜欢将doall
或vec
放在需要的地方。如果你把它放在一个长的处理链的末端,它为什么会在那里并不明显,当有人改变或删除一个“不需要的”步骤时,它可能会导致错误。特别是如果最后一步像将mapv
更改为map
这样微妙,我不同意艾伦的观点。我会坚持使用doall
在您拥有它的地方:使用open围绕内部的代码体。直接将doall
包装在行seq
代码周围将强制将其全部读取到内存中,如果传入的fn
减少了数据大小——就像这个(map count x)
所做的那样——您将希望在非常大的文件上使用行seq
的惰性,使用文件在内部执行doall还有另一个风险-它期望fn
返回一个序列。例如,如果在上爆炸(使用文件…计数)
。我希望fn
不要偷懒。另外,请澄清参数名称,如fn
=>f
或fn
。另外,我会直接用doall
或vec
来包装行序列
,比如:(f(vec(lineseq r)))
。直接用doal来包装行序列不会破坏使用惰性序列的整个目的吗?它将全部加载到内存中,但对于大多数目的来说,这并没有什么区别。除非确实需要延迟处理管道,否则我喜欢将doall
或vec
放在需要的地方。如果你把它放在一个长的处理链的末端,它为什么会在那里并不明显,当有人改变或删除一个“不需要的”步骤时,它可能会导致错误。特别是如果最后一步像将mapv
更改为map
这样微妙,我不同意艾伦的观点。我会坚持使用doall
在您拥有它的地方:使用open
围绕内部的代码体。直接将doall
包装在行seq
代码周围将强制将其全部读取到内存中,如果传入的fn
减少了数据大小——就像这个(map count x)
所做的那样——您将希望在非常大的文件上使用行seq
的惰性,使用文件在内部执行doall还有另一个风险-它期望fn
返回一个序列。例如,如果在上爆炸(使用文件…计数)
。我宁愿希望fn
不要懒惰。