Clojure中的循环定义

qed*_*qed 3 clojure

这是一个例子:

(defn f1 [] (lazy-seq (cons 0 (f2))))
(defn f2 [] (lazy-seq (cons 1 (f3))))
(defn f3 [] (lazy-seq (cons 2 (f1))))
Run Code Online (Sandbox Code Playgroud)

在Haskell中,上述示例的等价物将生成[0,1,2,0,1,2,...]的惰性序列,但在clojure中,这将导致CompilerException,因为f2无法解析.

有没有办法解决?

Art*_*ldt 8

用于declare创建前向声明

user> (declare f1) 
#'user/f1
user> (declare f2)
#'user/f2
user> (declare f3)
#'user/f3
Run Code Online (Sandbox Code Playgroud)

或作为缩略图指出:

user> (declare f1 f2 f3)
#'user/f3
Run Code Online (Sandbox Code Playgroud)

也有效

user> (defn f1 [] (lazy-seq (cons 0 (f2))))
#'user/f1
user> (defn f2 [] (lazy-seq (cons 1 (f3))))
 #'user/f2
user> (defn f3 [] (lazy-seq (cons 2 (f1))))
#'user/f3
Run Code Online (Sandbox Code Playgroud)

然后你得到你的递归懒惰序列:

user> (take 20 (f3))
(2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0)
Run Code Online (Sandbox Code Playgroud)

  • 目前的一次通过编译器设计很难实现,并且双通道编译器难以兼顾副作用宏扩展的可能性,以及其他问题 (3认同)

Thu*_*ail 8

如果您只想生成延迟序列,可以使用以下方法在本地定义一组相互递归的函数letfn:

(letfn [(f1 [] (lazy-seq (cons 0 (f2))))
        (f2 [] (lazy-seq (cons 1 (f3))))
        (f3 [] (lazy-seq (cons 2 (f1))))]
  (f1))

=> (0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 ...
Run Code Online (Sandbox Code Playgroud)