Ответ 1
Lazy-seq call просто выполняет тело после первого обращения к нему, затем кэширует и возвращает тот же результат, когда он снова будет вызван в будущем.
Если вы хотите использовать это для построения длинных (или даже бесконечных) последовательностей, вам необходимо рекурсивно вложить другие вызовы ленивого seq в возвращенной последовательности. Вот про самый простой случай, о котором я могу думать:
(defn ints-from [n]
(cons n (lazy-seq (ints-from (inc n)))))
(take 10 (ints-from 7))
=> (7 8 9 10 11 12 13 14 15 16)
Любой вызов (ints-from n) создает последовательность, начинающуюся с n, за которой следует ленивая последовательность (ints-from (inc n)). Это бесконечный список, но это не проблема, потому что lazy-seq гарантирует, что (int-from (inc n)) вызывается только тогда, когда это необходимо. Вы можете попробовать точно такой же код без ленивого seq, и вы быстро получите StackOverflowError.
lazy-seq - это всего лишь один из многих возможных способов создания ленивых последовательностей, и он часто не самый удобный. Ниже приведены некоторые другие интересные/полезные способы создания ленивых последовательностей:
; range is an easy way to get an infinite lazy sequence of integers, starting with zero
(take 10 (range))
=> (0 1 2 3 4 5 6 7 8 9)
; map produces lazy sequences, so the following is lazy
(take 10 (map #(* % %) (range)))
=> (0 1 4 9 16 25 36 49 64 81)
; iterate is a good way of making infinite sequenes of the form x, f(x), f(f(x)).....
(take 10 (iterate (partial * 2) 1))
=> (1 2 4 8 16 32 64 128 256 512)