Это не ответ на ваш вопрос, но в интересах написания «хорошего» кода clojure, я хотел бы указать на некоторые вещи с вашим примером.
Одним из преимуществ функционального стиля является способность создавать функции вместе. Но если вы посмотрите на функции, которые вы написали, они индивидуально не делают многого, не в зависимости от функциональности, предоставляемой в другом месте.
Например, stream-builder
просто возвращает список из двух элементов: n
и анонимную функцию для обработки псевдорекурсии.
Я предполагаю, что вы пытались идти на ленивую последовательность, но для этого требуются вспомогательные функции, которые знают о деталях реализации, чтобы реализовать следующий элемент, а именно: stream
и second$
. К счастью, вы можете вместо этого выполнить его следующим образом:
(defn stream-builder [f x] ; f is idiomatic for a function arg
(lazy-seq ; n is idiomatic for a count, so use x instead
(cons x
(stream-builder f (f x)))))
выше будет на самом деле возвращает бесконечную последовательность значений, так что мы должны вытащить предельное поведение, которая в комплекте внутри stream
:
(defn limit [n coll] ; coll is idiomatic for a collection arg
(lazy-seq ; flipped order, fns that work on seqs usually take the seq last
(when (pos? n)
(when-let [s (seq coll)]
(cons (first s)
(limit (dec n) (next s)))))))
выше будет лениво вернуться к n
элементов coll
:
user=> (limit 5 (stream-builder inc 1))
(1 2 3 4 5)
В конце каждая функция хорошо справляется и может быть скомбинирована с другими функциями:
Наконец, вы определили odd
как ленивую последовательность нечетных целых чисел. Опасность состоит в том, что последовательность будет придерживаться, когда она будет реализована (это называется «удерживание головы» последовательности). Это может излишне занять избыточную память, чтобы удерживать каждый элемент, когда-либо реализованный, и предотвращает сбор мусора.
Чтобы решить эту проблему, либо не DEF ленивой последовательности, или DEF его с пределом, например:
(def odds (limit 23 (stream-builder #(+ 2 %) 1)))
Для дальнейшего использования, что мы только что написали доступно в базовой Lib, как iterate
и take
, соответственно:
user=> (take 5 (iterate inc 1))
(1 2 3 4 5)
Я не уверен, что вы просите. Похоже, вы уже нашли для него 3 имени. Что, по вашему мнению, сделает любой ответ более «правильным», чем любой другой из этих синонимов? – Ken