I am doing this Clojure program for fibonacci series.
(def fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println '(a b c))
)(swap! n inc)))
(fibonacci)
I am getting this error:
CompilerException java.lang.RuntimeException: Too many arguments to def, compiling:(C:\Users\user\AppData\Local\Temp\form-init4960759414983563364.clj:1:1)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: fibonacci in this context, compiling:(C:\Users\user\AppData\Local\Temp\form-init4960759414983563364.clj:13:1)
I can't figure out how to reassign the variables a
, b
and c
. And also please suggest any correction needed in the program.
First, let's get your code working. The first def
, to define a function, should be defn
:
(defn fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println '(a b c))
)(swap! n inc)))
It compiles. Let's try it:
> (fibonacci)
(a b c)
(a b c)
...
(a b c)
=> nil
Not what you intended. The trouble is the quote in front of (a b c)
, which returns the elements of the list unevaluated. We have to take the quote off, but we don't want a
to be treated as an operator. So put in list
:
(defn fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println (list a b c))
)(swap! n inc)))
Let's run it:
> (fibonacci)
(0 0 0)
(0 0 0)
...
(0 0 0)
=> nil
Well, we got numbers, though not the ones we want. The problem is that the first (def c (+ a b))
wipes out the only non-zero value. We ought to start with b
at 1
, and just use c
temporarily:
(defn fibonacci []
(def a 0)
(def b 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println (list a b c))
)(swap! n inc)))
And now ...
> (fibonacci)
(1 1 1)
(1 2 2)
(2 3 3)
(3 5 5)
(5 8 8)
(8 13 13)
(13 21 21)
(21 34 34)
(34 55 55)
(55 89 89)
(89 144 144)
=> nil
Hurrah!
But we can see that b
and c
are the same, and just predict the next a
.
There is a bigger problem. Using mutable variables is not the Clojure way. Nor is it idiomatic for a function to print what it computes: better develop the result as a sequence, which we can do what we like with.
We can define the whole Fibonacci sequence thus:
(defn fibonacci []
(map second
(iterate
(fn [[a b]] [b (+ a b)])
[0 1])))
And just develop as much as we want:
(take 10 (fibonacci))
=> (1 1 2 3 5 8 13 21 34 55)