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.