Skip to content

Commit b988e8b

Browse files
committed
Add sequence-padded
1 parent 069f24c commit b988e8b

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

src/medley/core.cljc

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,22 @@
733733
(when (some identity ss)
734734
(cons (apply f (mapv #(first* % val) ss))
735735
(step (mapv rest ss)))))))]
736-
(step (conj colls c3 c2 c1))))))
736+
(step (conj colls c3 c2 c1))))))
737+
738+
(defn sequence-padded
739+
"Similar to `clojure.core/sequence`, except that it runs until all colls are
740+
exhausted, using `val` as the missing value for each exhausted coll."
741+
#_{:clj-kondo/ignore [:unused-binding]}
742+
([xform val c1] (sequence xform c1))
743+
([xform val c1 & colls]
744+
(let [f (xform conj)
745+
step (fn step [cs]
746+
(lazy-seq
747+
(let [ss (mapv seq cs)]
748+
(if (some identity ss)
749+
(let [res (apply f nil (mapv #(if % (first %) val) ss))]
750+
(cond (reduced? res) (f (deref res))
751+
(nil? res) (step (mapv rest ss))
752+
:else (concat res (lazy-seq (step (mapv rest ss))))))
753+
(f nil)))))]
754+
(step (conj colls c1)))))

test/medley/core_test.cljc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,43 @@
572572
[:missing :missing 4 4]
573573
[:missing :missing :missing 5]]
574574
(take 6 (m/map-padded vector :missing [nil nil nil] (range 4) (range 5) (range 10)))))))
575+
576+
(deftest test-sequence-padded
577+
(is (= (map + (range 3) (range 4) (range 5) (range 10))
578+
[0 4 8]
579+
(take 3 (m/sequence-padded (map +) 0 (range 3) (range 4) (range 5) (range 10)))))
580+
(is (= [0 4 8 19 28 35 36 37 38 39]
581+
(m/sequence-padded (map +) 10 (range 3) (range 4) (range 5) (range 10))))
582+
(is (= ()
583+
(m/sequence-padded (map +) 10 () () ())))
584+
(testing "laziness"
585+
(let [state (volatile! [])]
586+
(is (= [0 4 8 19 28]
587+
(take 5 (m/sequence-padded
588+
(map (fn [a b c d]
589+
(vswap! state conj [a b c d])
590+
(+ a b c d)))
591+
10
592+
(range 3) (range 4) (range 5) (range 10)))))
593+
(is (= [[0 0 0 0] [1 1 1 1] [2 2 2 2] [10 3 3 3] [10 10 4 4]]
594+
@state))))
595+
(testing "handles sequences with nils"
596+
(is (= [[nil 0 0 0] [nil 1 1 1] [nil 2 2 2]
597+
[:missing 3 3 3]
598+
[:missing :missing 4 4]
599+
[:missing :missing :missing 5]]
600+
(take 6 (m/sequence-padded (map vector) :missing [nil nil nil] (range 4) (range 5) (range 10))))))
601+
(testing "slightly more complex xform"
602+
(let [xf
603+
(comp
604+
(map vector)
605+
(drop 5)
606+
(filter (comp even? second))
607+
(map #(mapv inc %))
608+
(take 5))]
609+
(is (= [[101 19 507] [101 25 509] [101 31 511] [101 37 513] [101 43 515]]
610+
(m/sequence-padded xf
611+
100
612+
(range 5)
613+
(range 0 50 3)
614+
(range 500 1000)))))))

0 commit comments

Comments
 (0)