Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure lazy seq over Java迭代代码_Clojure_Iteration - Fatal编程技术网

Clojure lazy seq over Java迭代代码

Clojure lazy seq over Java迭代代码,clojure,iteration,Clojure,Iteration,我试图使用继承的一些迭代Java库代码创建Clojure seq。基本上,Java代码所做的是使用解析器从文件中读取记录,将这些记录发送到处理器并返回结果的ArrayList。在Java中,这是通过调用parser.readData(),然后调用parser.getRecord()来获取记录,然后将该记录传递给processor.processRecord()。每次调用parser.readData()都会返回一条记录,如果没有更多记录,则返回null。Java中非常常见的模式 所以我在Cloj

我试图使用继承的一些迭代Java库代码创建Clojure seq。基本上,Java代码所做的是使用解析器从文件中读取记录,将这些记录发送到处理器并返回结果的ArrayList。在Java中,这是通过调用parser.readData(),然后调用parser.getRecord()来获取记录,然后将该记录传递给processor.processRecord()。每次调用parser.readData()都会返回一条记录,如果没有更多记录,则返回null。Java中非常常见的模式

所以我在Clojure中创建了这个next record函数,它将从解析器中获取下一条记录

(defn next-record
  "Get the next record from the parser and process it."
  [parser processor]
  (let [datamap (.readData parser)
        row (.getRecord parser datamap)]
    (if (nil? row)
    nil
    (.processRecord processor row 100))))
然后,我们的想法是调用该函数并将记录累积到Clojure seq(最好是惰性seq)中。这是我的第一次尝试,只要记录不太多,效果就很好:

(defn datamap-seq
  "Returns a lazy seq of the records using the given parser and processor"
  [parser processor]
  (lazy-seq
    (when-let [records (next-record parser processor)]
      (cons records (datamap-seq parser processor)))))
我可以创建一个解析器和处理器,并执行类似的操作(以5(datamap seq parser processor)为例),这将为我提供一个惰性seq。正如预期的那样,获取该seq的(第一个)只实现一个元素,进行count实现所有元素,等等。这正是我期望从一个懒惰的seq获得的行为

当然,当有很多记录时,我最终得到了StackOverflowException。所以我的下一个尝试是使用循环重现来做同样的事情

(defn datamap-seq
  "Returns a lazy seq of the records using the given parser and processor"
  [parser processor]
  (lazy-seq
    (loop [records (seq '())]
      (if-let [record (next-record parser processor)]
        (recur (cons record records))
        records))))
现在以同样的方式使用它,并使用(def results(datamap seq parser processor))定义它,这给了我一个惰性seq,并且没有实现任何元素。然而,一旦我做了其他事情,比如(第一个结果),它就会强制实现整个seq

有人能帮我理解在第二个函数中,使用循环递归导致它实现整个过程的错误所在吗

更新:

我仔细查看了异常的堆栈跟踪,堆栈溢出异常是从一个Java类抛出的。但只有当我有像这样的datamap seq函数(我在上面发布的函数确实有效)时,才会发生这种情况:

我真的不明白为什么删除会导致问题,但是当我将它从这个函数中取出时,它就可以正常工作了(我现在正在其他地方删除空列表)。

循环/重复循环表达式中的循环,直到递归结束。在它周围添加一个懒惰的seq不会阻止这一点

第一次尝试使用lazy seq/cons应该已经可以正常工作了,不会出现堆栈溢出。我现在无法发现它的问题是什么,尽管它可能在代码的java部分。

循环/在循环表达式中重复循环,直到递归结束。在它周围添加一个懒惰的seq不会阻止这一点


第一次尝试使用lazy seq/cons应该已经可以正常工作了,不会出现堆栈溢出。我现在无法发现它的问题是什么,尽管它可能在代码的java部分。

我将在这里发布Joost答案的补充。此代码:

(defn integers [start] (lazy-seq (cons start (integers (inc start))))) 编辑:

当然,更好的方法是
(iterate inc 0)
:)

编辑2:

我将尝试解释一下lazy seq是如何工作的。是一个返回类seq对象的宏。再加上这一点,直到有人要求你懒惰时,你才意识到它的第二个论点

现在看一下是如何实现的
LazySeq.sval
触发下一个值的计算,该值返回另一个“冻结”惰性序列实例。该方法更能说明概念背后的机制。请注意,为了完全实现序列,它使用while循环。它本身意味着堆栈跟踪的使用仅限于返回另一个LazySeq实例的短函数调用


我希望这有意义。我描述了我可以从源代码中推断出什么。如果我有任何错误,请告诉我。

我将在这里发布Joost答案的补充内容。此代码:

(defn integers [start] (lazy-seq (cons start (integers (inc start))))) 编辑:

当然,更好的方法是
(iterate inc 0)
:)

编辑2:

我将尝试解释一下lazy seq是如何工作的。是一个返回类seq对象的宏。再加上这一点,直到有人要求你懒惰时,你才意识到它的第二个论点

现在看一下是如何实现的
LazySeq.sval
触发下一个值的计算,该值返回另一个“冻结”惰性序列实例。该方法更能说明概念背后的机制。请注意,为了完全实现序列,它使用while循环。它本身意味着堆栈跟踪的使用仅限于返回另一个LazySeq实例的短函数调用


我希望这有意义。我描述了我可以从源代码中推断出什么。如果我有任何错误,请告诉我。

完全同意。问Dave,你能把堆栈跟踪粘贴到这里吗?我认为您的lazy-seq实现没有任何问题。感谢您的回复。当我看到StackOverflowException时,我立即跳转到递归问题,而没有真正查看堆栈跟踪。该异常实际上是由Java代码引发的,是Emacs内部多次运行而未清除状态的结果。但是现在我不明白为什么你说第一个代码不会导致堆栈溢出。这很容易解释吗?或者你可以给我指一个参考资料吗?也谢谢你用循环/重现表达式解释我错误的想法。达维金卡说:“现在这很有道理了。”我在懒洋洋的seq后面贴了一个力学解释,作为对我答案的编辑(太长了,无法放在这里)。完全同意。问Dave,你能把堆栈跟踪粘贴到这里吗?我认为您的lazy-seq实现没有任何问题。感谢您的回复。当我看到StackOverflowException时,我立即跳转到递归问题,而没有真正查看堆栈跟踪。该异常实际上是由Java代码引发的,是Emacs内部多次运行而未清除状态的结果。但是现在我不明白为什么你说第一个代码不会导致堆栈溢出。这很容易解释还是我
(take 5 (drop 1000000 (integers)))