This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-07
Channels
- # adventofcode (3)
- # announcements (6)
- # babashka (20)
- # beginners (53)
- # calva (11)
- # clj-kondo (11)
- # clojure (50)
- # clojure-argentina (4)
- # clojure-dev (1)
- # clojure-europe (14)
- # clojure-houston (1)
- # clojure-italy (2)
- # clojure-nl (4)
- # clojure-norway (3)
- # clojure-seattle (3)
- # clojure-uk (13)
- # clojurescript (2)
- # cloverage (1)
- # code-reviews (4)
- # conjure (2)
- # cursive (5)
- # datalevin (4)
- # datascript (33)
- # datomic (16)
- # events (1)
- # graphql (10)
- # gratitude (1)
- # honeysql (6)
- # introduce-yourself (2)
- # jobs (1)
- # lsp (88)
- # malli (8)
- # off-topic (3)
- # other-languages (4)
- # polylith (3)
- # re-frame (16)
- # reagent (17)
- # reitit (3)
- # releases (2)
- # remote-jobs (1)
- # rewrite-clj (3)
- # shadow-cljs (3)
- # slack-help (2)
- # sql (36)
- # testing (31)
- # tools-deps (41)
- # xtdb (23)
Hi friends! For writing a lazy-seq which of this implementations is preferred?
;; wrap the tail
(defn drop-after
[p? s]
(when (seq s)
(let [head (first s)]
(if (p? head)
[head]
(cons head (lazy-seq (drop-after p? (rest s))))))))
;; wrap everything
(defn drop-after
[p? s]
(lazy-seq
(when (seq s)
(let [head (first s)]
(if (p? head)
[head]
(cons head (drop-after p? (rest s))))))))
howdy! on the subject of lazy-seq "wrap everything vs wrap tail"
I recently find out that wrapping everything may cause stackoverflow when interleaving and concating lazy sequences, while wrapping the tail does not.
if everything is wrap when doing a
(seq some-lazy-seq)
causes the whole seq to be realized combining lazy-sequences, while if only the tail is wrap (seq (cons h some-lazy-seq))
wont realized the whole seq.Also destructuring
(let [[h & t] some-lazy-seq] ...)
causes the seq to be realized, I think the macro expansion introduces a call to seq
.
Sorry, I was wrong, but I was almost right. I've read this article https://stuartsierra.com/2015/04/26/clojure-donts-concat then I asked my self what if only wrap the tail. I didn't realized, that the head is always realized, but the tail will blowup anyway.
(defn concat-tail [x y]
(if (seq x)
(cons (first x)
(lazy-seq (concat-tail (rest x) y)))
y))
(defn concat-all [x y]
(lazy-seq
(if (seq x)
(cons (first x)
(concat-all (rest x) y))
y)))
(defn build-result [n cat]
(loop [counter 1
results []]
(if (< counter n)
(recur (inc counter)
(cat results (range 1 counter)))
results)))
(do (seq (build-result 4000 concat-all))
nil) ;; stackoverflow
(do (seq (build-result 4000 concat-tail))
nil) ;; it's ok
(->> (build-result 4000 concat-all)
(take 1)) ;; stackoverflow
(->> (build-result 4000 concat-tail)
(take 1)) ;; it's ok
(->> (build-result 4000 concat-all)
(take 2)) ;; stackoverflow
(->> (build-result 4000 concat-tail)
(take 2)) ;; stackoverflow blows up anyway
howdy! on the subject of lazy-seq "wrap everything vs wrap tail"
I recently find out that wrapping everything may cause stackoverflow when interleaving and concating lazy sequences, while wrapping the tail does not.
if everything is wrap when doing a
(seq some-lazy-seq)
causes the whole seq to be realized combining lazy-sequences, while if only the tail is wrap (seq (cons h some-lazy-seq))
wont realized the whole seq.Also destructuring
(let [[h & t] some-lazy-seq] ...)
causes the seq to be realized, I think the macro expansion introduces a call to seq
.