Clojure ленивый внутри применяется

Я пытаюсь прочитать в файл построчно и объединить новую строку в конце каждой строки. Для тестирования я сделал это:

(defn read-file
[filename]
(with-open [rdr (clojure.java.io/reader filename)]
  (doall (line-seq rdr))))

(apply str ["asdfasdf" (doall (take 1 (read-file filename)))])

Если я просто оцениваю (take 1 (read-file filename)) в ответ я получаю первую строку файла. Однако, когда я пытаюсь оценить, что я сделал выше, я получаю "asdfasdfclojure.lang.LazySeq@4be5d1db",

Может кто-нибудь объяснить, как насильно оценить take заставить его не возвращать ленивую последовательность?

1 ответ

Решение

take Функция ленива по своей структуре, поэтому вам, возможно, придется реализовать нужные значения, используя first, next, или же nth или оперируйте всем последующим с помощью таких функций, как apply, reduce, vec, или же into,

В вашем случае, похоже, вы пытаетесь сделать следующее:

(apply str ["asdfasdf" (apply str (take 1 (read-file filename)))])

Или же:

(str "asdfasdf" (first (read-file filename)))


Вы также можете реализовать весь lazyseq, используя doall, Просто имейте в виду, реализованный ленивый seq все еще seq.

(realized? (take 1 (read-file filename))) ;; => false
(type (take 1 (read-file filename))) ;; => clojure.lang.LazySeq

(realized? (doall (take 1 (read-file filename)))) ;; => true
(type (doall (take 1 (read-file filename)))) ;; => clojure.lang.LazySeq


Лучшим вариантом было бы применять ваши преобразования лениво, используя что-то вроде map и выберите нужные значения из полученного в результате. (Как потоковая обработка.)

(first (map #(str "prefix" % "suffix")
             (read-file filename)))

Замечания: map ленивый, поэтому он вернет нереализованный LazySeq.

Другие вопросы по тегам