Я пробовал в Clojure следующее, ожидая возврата класса неленивой последовательности:
(.getClass (doall (take 3 (repeatedly rand))))
Однако это все равно возвращается clojure.lang.LazySeq
. Я предполагаю, что doall
это оценивает всю последовательность, но возвращает исходную последовательность, поскольку она все еще полезна для мемоизации.
Итак, каковы идиоматические средства создания неленивых последовательностей из ленивых?
clojure
lazy-evaluation
Тим Клемонс
источник
источник
doall
(vec (take 3 (repeatedly rand)))
Ответы:
doall
это все, что тебе нужно. Просто потому, чтоseq
тип hasLazySeq
не означает, что он ожидает оценки. Lazyseq
кэширует свои результаты, поэтому все, что вам нужно сделать, этоseq
один раз пройтись с ленивым (как этоdoall
происходит), чтобы заставить все это и, таким образом, сделать его неленивым.seq
это не заставит всю коллекцию , чтобы оценить.источник
realized?
.realize
операция для сопоставленияrealized?
.contains?
, не заботятся о том, реализовали ли вы ленивую последовательность или нет, это отвечает на заданный конкретный вопрос, но в меньшей степени на заголовок вопроса.В некоторой степени это вопрос таксономии. Ленивая последовательность - это всего лишь один тип последовательности, такой как список, вектор или карта. Итак, ответ, конечно, «это зависит от того, какой тип неленивой последовательности вы хотите получить:
выберите из:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
Вы можете выбрать любой тип последовательности, который больше всего соответствует вашим потребностям.
источник
(vec (my-lazy-seq))
не так хорош в следующих ситуациях:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Т.к.cheshire
выбирает создание lazy-seq из(json/parse-string)
(json/parse-string-strict)
Этот Богатый парень, кажется, знает свое закрытие и абсолютно прав.
Но я думаю, что этот фрагмент кода, используя ваш пример, может быть полезным дополнением к этому вопросу:
Действительно, тип не изменился, но реализация изменилась.
источник
realized?
возвращать всю последовательностьtrue
. Например(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
[true true]
Я наткнулся на это сообщение в блоге о том, что он
doall
не рекурсивен. Для этого я обнаружил, что первый комментарий в посте помог. Что-то вроде:Я нашел это полезным в модульном тесте, где я хотел принудительно выполнить оценку некоторых вложенных приложений,
map
чтобы вызвать состояние ошибки.источник
источник