Circular definition in Clojure

Here's an example:

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

      

In Haskell, the equivalent of the above example would result in the lazy sequence [0, 1, 2, 0, 1, 2, ...], but in clojure this would throw a CompilerException because it f2

could not be resolved.

Is there a way to get around this?

+3


source to share


2 answers


use declare

to create forward ads

user> (declare f1) 
#'user/f1
user> (declare f2)
#'user/f2
user> (declare f3)
#'user/f3

      

or as a Thumbnail icon:

user> (declare f1 f2 f3)
#'user/f3

      



works also

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

      

then you end up with your recursive lazy sequence:

user> (take 20 (f3))
(2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0)

      

+8


source


If you just want to create a lazy sequence, you can localize a bunch of mutually recursive functions with 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 ...

      

+8


source







All Articles