Во-первых, давайте сделаем ваш код работающим.Первый def
, для определения функции, должен быть 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)))
. Компилируется.Давайте попробуем это:
> (fibonacci)
(a b c)
(a b c)
...
(a b c)
=> nil
Не то, что вы хотели.Беда в кавычке перед (a b c)
, которая возвращает элементы списка без оценки.Мы должны снять цитату, но мы не хотим, чтобы a
рассматривался как оператор.Итак, вставьте 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)))
Давайте запустим это:
> (fibonacci)
(0 0 0)
(0 0 0)
...
(0 0 0)
=> nil
Ну, у нас есть числа, но не те, которые мы хотим.Проблема в том, что первый (def c (+ a b))
стирает единственное ненулевое значение.Мы должны начать с b
в 1
и просто временно использовать c
:
(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)))
А теперь ...
> (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
Ура!
Но мы можем видеть, что b
и c
одинаковы, и просто предсказать следующее a
.
Есть большая проблема.Использование изменяемых переменных не является способом Clojure.Также не идиоматично для функции печатать то, что она вычисляет: лучше развивать результат в виде последовательности, с которой мы можем делать то, что нам нравится.
Мы можем определить всю последовательность Фибоначчи следующим образом:
(defn fibonacci []
(map second
(iterate
(fn [[a b]] [b (+ a b)])
[0 1])))
И просто развивать столько, сколько мы хотим:
(take 10 (fibonacci))
=> (1 1 2 3 5 8 13 21 34 55)