Clojure 什么';这个函数的返回值是多少?

Clojure 什么';这个函数的返回值是多少?,clojure,Clojure,我写了这个函数,但是它的返回值是多少 (defn read-data [file] (let [code (subs (.getName file) 0 3)] (with-open [rdr (clojure.java.io/reader file)] (drop 1 (line-seq rdr))))) (def d (read-data "data.db")) 直到现在还可以。但当我想打印出来的时候 (clojure.pprint/pprint d) 我有一个

我写了这个函数,但是它的返回值是多少

(defn read-data [file]
  (let [code (subs (.getName file) 0 3)]
    (with-open [rdr (clojure.java.io/reader file)]
      (drop 1 (line-seq rdr)))))

(def d (read-data "data.db"))
直到现在还可以。但当我想打印出来的时候

(clojure.pprint/pprint d)
我有一个例外:

Exception in thread "main" java.lang.RuntimeException: java.io.IOException: Stream closed
所以我很困惑,怎么了?返回值不是一个列表?作为新手,在这种情况下如何调试

谢谢

(drop 1 (line-seq rdr))
此行返回一个序列,即惰性或流。因此,当执行这一行时,文件读取器rdr基本上不会被实际读取,但当您尝试在打印方法中访问此序列时,rdr会被
行序列
函数读取,但当您使用
with open
时,当执行从
with open
流出时,rdr已经关闭


请参阅
doall
,以便在创建惰性序列时对其进行求值。我建议您阅读FP中的惰性,尤其是序列,以便Clojure更好地理解惰性评估。

问题在于
行序列
是惰性的,并且在评估时阅读器已关闭

这意味着所有行都需要在使用open的
范围内读取。一个选项是使用
doall
强制对
line seq
进行完整评估,如下所示

(drop 1 (doall (line-seq rdr)))

这种方法的一个潜在问题是,如果文件大于可用内存,则会出现OutOfMemoryError。因此,根据您试图实现的目标,可能还有其他内存占用较少的解决方案。

例如,您可以使用close和修改后的“line seq”来自动关闭读卡器:

(defn line-seq2 [^java.io.BufferedReader rdr]
  (if-let [line (.readLine rdr)]
    (cons line (lazy-seq (line-seq2 rdr)))
    (.close rdr)))

(defn my-reader [file]
  (let [lines (line-seq (clojure.java.io/reader file))]
    (fn [] lines)))

(def d (my-reader "data.db"))
现在变量“d”是一个函数:

user> (drop 1 (d))
=> ... file body except first line ...