Функционально-локальная, самореферентная, ленивая последовательность Фибоначчи
Я хотел бы создать функцию, которая возвращает лениво расширенную бесконечную последовательность чисел Фибоначчи.
Прямо сейчас я могу сделать свою последовательность доступной в пространстве имен верхнего уровня следующим образом:
(def fibonacci-numbers
(lazy-cat [0 1] (map + fibonacci-numbers (rest fibonacci-numbers))))
Однако это означает, что если я начну потреблять много из них, я потеряю контроль над сборкой мусора.
Я хочу сделать что-то вроде:
(defn fibonacci-numbers-fn []
(lazy-cat [0 1] (map + (fibonacci-numbers-fn) (rest (fibonacci-numbers-fn)))))
Это явно не будет работать, потому что я в конечном итоге создаю O (2 ^ n) последовательностей. Я думаю, что спрашиваю, как создать само-ссылочную ленивую последовательность в пространстве имен локальной функции. Что я должен делать?
РЕДАКТИРОВАТЬ: Хотя мне нравится популярное решение, опубликованное Амаллой и найдено по всему Интернетуdefn fibs [] (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
Меня интересует версия, похожая на канонический способ Haskell:
fibonaccis = 0 : 1 : zipWith (+) fibonaccis (tail fibonaccis)
Это то, что я пытался выполнить с моей первоначальной функцией. Для меня решение с итерацией карты выглядит следующим образом: «добавьте два предыдущих элемента, чтобы создать новый». и решение для ленивого кота читается как «присоединиться к потоку с его первым запаздыванием». Как я могу "присоединиться к потоку с его первой задержкой"? не имея последовательности в пространстве имен верхнего уровня?