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
Recursion 递归使用'lazy seq'会占用堆栈帧吗?_Recursion_Clojure_Lazy Sequences - Fatal编程技术网

Recursion 递归使用'lazy seq'会占用堆栈帧吗?

Recursion 递归使用'lazy seq'会占用堆栈帧吗?,recursion,clojure,lazy-sequences,Recursion,Clojure,Lazy Sequences,目前我正在学习lazy-seq,我注意到它们通常涉及递归,而不使用recur。例如,下面是iterate的实现: (defn iterate "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects" {:added "1.0" :static true} [f x] (cons x (lazy-seq (iterate f (f x))))) 我的印象是,如果您在不

目前我正在学习lazy-seq,我注意到它们通常涉及递归,而不使用
recur
。例如,下面是
iterate
的实现:

(defn iterate
  "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
  {:added "1.0"
   :static true}
  [f x] (cons x (lazy-seq (iterate f (f x)))))
我的印象是,如果您在不使用
recur
的情况下进行递归,它将为每个调用生成一个新的堆栈帧,如果您迭代足够多的时间,这可能会导致堆栈溢出


lazy seq
是否会吞噬堆栈帧?如果没有,它如何避免呢?

没有懒惰的seq不会吞噬堆栈帧

从这段代码的表面上看,它似乎是一个递归调用,但lazy seq不是一个函数,它是一个宏,在这种特殊情况下,它将转换为:

(惰性seq(迭代f(f x))

变得有点像

(新的clojure.lang.LazySeq(fn[](迭代f(f x)))


正如您所看到的,迭代函数调用被包装在另一个函数中(这使它变得懒惰,即稍后将调用该函数).

在本例中,当您看到lazy seq包含一个迭代调用时,它实际上不是递归的。相反,当您请求第二个项时,lazy seq宏将自身展开为一个挂起的调用。因此,每次检索一个项时,您都会引起一次调用,但旧调用不在堆栈上

另一个有趣的问题是您是否正在消耗内存,这取决于您对序列头所做的操作。如果您保留在var或本地绑定中,整个cons单元格链将被保留。如果您避免保留头部,并沿序列向下移动,GC可以在您后面清理

一个棘手的问题是lazy-seq宏中有一些特殊的元^{:once-true},它让编译器知道fn闭包是一次性的,并且不保留任何闭合变量