Как конвертировать ленивый последовательности, чтобы не лениться в Clojure


я попробовал следующее в Clojure, ожидая, что будет возвращен класс не ленивой последовательности:

(.getClass (doall (take 3 (repeatedly rand))))

однако, это все еще возвращает clojure.lang.LazySeq. Я предполагаю, что doall оценивает всю последовательность, но возвращает исходную последовательность, поскольку она по-прежнему полезна для запоминания.

Итак, что такое идиоматические средства создания не ленивой последовательности из ленивой?

5 86

5 ответов:

doall все, что вам нужно. Просто потому, что seq имеет тип LazySeq, это не значит, что он ожидает оценки. Ленивые seqs кэшируют свои результаты, поэтому все, что вам нужно сделать, это пройти ленивый seq один раз (как это делает doall), чтобы заставить его все, и, таким образом, сделать его не ленивым. seq, совсем не принудительно оценить всю коллекцию.

Это в какой-то степени вопрос таксономии. ленивая последовательность-это только один тип последовательности как список, вектор или карту. Поэтому ответ, Конечно, " это зависит от того, какой тип не ленивой последовательности вы хотите получить:
Сделайте свой выбор:

  • бывшая ленивая (полностью оцененная) ленивая последовательность (doall ... )
  • список для последовательного доступа (apply list (my-lazy-seq)) OR (into () ...)
  • вектор для последующего произвольного доступа (vec (my-lazy-seq))
  • карта или набор если у вас есть какая-то особая цель.

вы можете иметь любой тип последовательности наиболее соответствует вашим потребностям.

этот богатый парень, кажется, знает его Clojure и абсолютно прав.
Но я думаю, что этот фрагмент кода, используя Ваш пример, может быть полезным дополнением к этому вопросу:

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

действительно тип не изменилась, но реализация и

я наткнулся на это это блог пост про doall не являющийся рекурсивным. Для этого я нашел первый комментарий в посте сделал свое дело. Что-то вроде:

(use 'closure.walk)
(postwalk identity nested-lazy-thing)

Я нашел это полезным в модульном тесте, где я хотел заставить оценку некоторых вложенных приложений map для принудительного выполнения условия ошибки.

(.getClass (into '() (take 3 (repeatedly rand))))