Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bind expression which uses itself? [duplicate]

Tags:

clojure

Cause I have a lazy-seq to calculate fibonacci sequence.

(def fibonacci
  (lazy-cat [0 1] (map + fibonacci (rest fibonacci))))
=> #'user/fibonacci
(take 10 fibonacci)
=> (0 1 1 2 3 5 8 13 21 34)

But when I try to put fibonacci into let

(let [fibonacci
  (lazy-cat [0 1] (map + fibonacci (rest fibonacci)))]
  (take 10 fibonacci))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: fibonacci in this context, compiling:...

How to solve it?

like image 615
speedcell4 Avatar asked Mar 14 '23 20:03

speedcell4


1 Answers

Unlike with def, the binding of x to f made by (let [x f] ...) is not visible inside f. More precisely, binding to x is done after evaluating f. In order to have recursive definitions, you need to use letfn, which is for defining functions. Consequently, you can no longer treat fibonacci as a LazySeq, but you can define it as a function returning a LazySeq:

(letfn [(fibonacci [] 
          (lazy-cat [0 1] (map + (fibonacci) (rest (fibonacci)))))]
  (take 10 (fibonacci)))
like image 178
coredump Avatar answered Mar 19 '23 23:03

coredump