Как преобразовать ленивую последовательность в не ленивую в Clojure

StackOverflow https://stackoverflow.com/questions/1641626

  •  10-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

=> (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))))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top