Какой смысл в лени-сэке в clojure?

Я просматриваю пример кода последовательности Фибоначчи:

 (def fibs (lazy-cat [1 2] (map + fibs (rest fibs))))

Я вообще понимаю, что происходит, но не понимаю lazy-cat, я знаю это lazy-cat это макрос, который переводит что-то вроде этого:

(def fibs (concat (lazy-seq [1 2]) (lazy-seq (map + fibs (rest fibs))))) 

Что именно lazy-seq достижения? Это все равно будет оцениваться лениво, даже без lazy-seq? Это строго для целей кэширования?

РЕДАКТИРОВАТЬ: Спасибо за ответы. Мое замешательство было то, что это работало с простой concat из REPL, потому что у меня была предыдущая привязка к выдумкам в области видимости.

2 ответа

Решение

lazy-seq на [1 2] не нужно, но на самом деле не больно.

lazy-seq на (map + fibs (rest fibs)) необходимо; без него вызов функции будет оценен до fibs привязан к значению, которое вызовет исключение. Заворачивая это в lazy-seqвызов будет отложен до получения значения, и fibs будет иметь значение в этой точке.

Насколько я понимаю (и я признаю, что все еще являюсь относительным новичком в Clojure!), Если вы попробуете следующее:

(def fibs (concat [1 2] (map + fibs (rest fibs))))

Тогда это не сработает, потому что выдумки еще не связаны, и поэтому две более поздние ссылки на него терпят неудачу.

Однако ленивая версия, которую вы дадите, будет работать, потому что ссылки на FIB-ы на самом деле разрешаются только в более позднее время, когда используется последовательность - и к этому моменту FIB-ы уже были успешно определены как Lazy-последовательность.

Другие вопросы по тегам