Skip to content

Commit 19ad10e

Browse files
committed
[wip] support generators in seq processing fns
1 parent 50b9c45 commit 19ad10e

File tree

2 files changed

+130
-36
lines changed

2 files changed

+130
-36
lines changed

src/basilisp/core.lpy

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,7 @@
21872187
[coll]
21882188
(let [do-reverse (fn do-reverse
21892189
[in out]
2190-
(if (seq in)
2190+
(if-let [in (seq in)]
21912191
(recur (rest in) (cons (first in) out))
21922192
out))]
21932193
(do-reverse coll '())))
@@ -2668,10 +2668,11 @@
26682668
(defn every?
26692669
"Return ``true`` if every element in ``coll`` satisfies ``pred``\\."
26702670
[pred coll]
2671-
(cond
2672-
(nil? (seq coll)) true
2673-
(pred (first coll)) (recur pred (rest coll))
2674-
:else false))
2671+
(let [coll (seq coll)]
2672+
(cond
2673+
(nil? coll) true
2674+
(pred (first coll)) (recur pred (rest coll))
2675+
:else false)))
26752676

26762677
(defn every-pred
26772678
"Return a predicate composed of all of the input predicates, which returns ``true``
@@ -2700,7 +2701,7 @@
27002701
(defn some
27012702
"Return ``true`` if at least one element in ``coll`` satisfies ``pred``\\."
27022703
[pred coll]
2703-
(when (seq coll)
2704+
(when-let [coll (seq coll)]
27042705
(or (pred (first coll))
27052706
(recur pred (rest coll)))))
27062707

@@ -2745,13 +2746,15 @@
27452746
(rf result (apply f input inputs))))))
27462747
([f coll]
27472748
(lazy-seq
2748-
(when (seq coll)
2749+
(when-let [coll (seq coll)]
27492750
(cons (f (first coll)) (map f (rest coll))))))
27502751
([f coll & colls]
27512752
(lazy-seq
2752-
(when (and (seq coll) (every? seq colls))
2753-
(cons (apply f (first coll) (map first colls))
2754-
(apply map f (rest coll) (map rest colls)))))))
2753+
(when-let [coll (seq coll)]
2754+
(let [colls (map seq colls)]
2755+
(when (every? some? colls)
2756+
(cons (apply f (first coll) (map first colls))
2757+
(apply map f (rest coll) (map rest colls)))))))))
27552758

27562759
(def ^{:doc "Return a vector of ``(f elem)`` for elements in ``coll``\\. More than one
27572760
collection may be supplied. If more than one collection is supplied, the
@@ -2806,7 +2809,7 @@
28062809
result)))))
28072810
([pred coll]
28082811
(lazy-seq
2809-
(when (seq coll)
2812+
(when-let [coll (seq coll)]
28102813
(if (pred (first coll))
28112814
(cons (first coll) (filter pred (rest coll)))
28122815
(filter pred (rest coll)))))))
@@ -2841,7 +2844,7 @@
28412844
(rf result v)))))))
28422845
([f coll]
28432846
(lazy-seq
2844-
(when (seq coll)
2847+
(when-let [coll (seq coll)]
28452848
(let [elem (f (first coll))]
28462849
(if (nil? elem)
28472850
(keep f (rest coll))
@@ -2867,7 +2870,7 @@
28672870
(let [keep-idx (fn keep-idx
28682871
[rng coll]
28692872
(lazy-seq
2870-
(when (seq coll)
2873+
(when-let [coll (seq coll)]
28712874
(let [elem (f (first rng) (first coll))]
28722875
(if (nil? elem)
28732876
(keep-idx (rest rng) (rest coll))
@@ -2889,7 +2892,7 @@
28892892
([n coll]
28902893
(lazy-seq
28912894
(when (> n 0)
2892-
(when (seq coll)
2895+
(when-let [coll (seq coll)]
28932896
(cons (first coll) (take (dec n) (rest coll))))))))
28942897

28952898
(defn take-while
@@ -2907,7 +2910,7 @@
29072910
(ensure-reduced result))))))
29082911
([pred coll]
29092912
(lazy-seq
2910-
(when (seq coll)
2913+
(when-let [coll (seq coll)]
29112914
(when (pred (first coll))
29122915
(cons (first coll) (take-while pred (rest coll))))))))
29132916

@@ -2927,7 +2930,7 @@
29272930
(rf result input)))))))
29282931
([n coll]
29292932
(lazy-seq
2930-
(when (seq coll)
2933+
(when-let [coll (seq coll)]
29312934
(if (> n 0)
29322935
(drop (dec n) (rest coll))
29332936
(seq coll))))))
@@ -2949,7 +2952,7 @@
29492952
:else result))))))
29502953
([pred coll]
29512954
(lazy-seq
2952-
(when (seq coll)
2955+
(when-let [coll (seq coll)]
29532956
(if (pred (first coll))
29542957
(drop-while pred (rest coll))
29552958
(seq coll))))))
@@ -3019,7 +3022,7 @@
30193022
(rf (rf result sep) input)))))))
30203023
([sep coll]
30213024
(lazy-seq
3022-
(when (seq coll)
3025+
(when-let [coll (seq coll)]
30233026
(if (seq (rest coll))
30243027
(cons (first coll)
30253028
(cons sep (interpose sep (rest coll))))
@@ -3038,14 +3041,17 @@
30383041
(when (seq colls)
30393042
(cons (ffirst colls) (apply coll-firsts (rest colls))))))]
30403043
(lazy-seq
3041-
(when (and (seq coll) (every? seq colls))
3042-
(concat (apply coll-firsts coll colls)
3043-
(apply interleave (rest coll) (map rest colls))))))))
3044+
(when-let [coll (seq coll)]
3045+
(let [colls (map seq colls)]
3046+
(when (every? some? colls)
3047+
(concat (apply coll-firsts coll colls)
3048+
(apply interleave (rest coll) (map rest colls))))))))))
30443049

30453050
(defn cycle
30463051
"Cycle the items in ``coll`` infinitely."
30473052
[coll]
3048-
(let [coll-cycle (fn coll-cycle
3053+
(let [coll (seq coll)
3054+
coll-cycle (fn coll-cycle
30493055
[curr]
30503056
(lazy-seq
30513057
(if (seq curr)
@@ -3091,7 +3097,7 @@
30913097
result)))))))
30923098
([n coll]
30933099
(lazy-seq
3094-
(when (seq coll)
3100+
(when-let [coll (seq coll)]
30953101
(if (<= n 0)
30963102
(repeat (first coll))
30973103
(cons (first coll)
@@ -3108,13 +3114,13 @@
31083114
(partition n n coll))
31093115
([n step coll]
31103116
(lazy-seq
3111-
(when (seq coll)
3117+
(when-let [coll (seq coll)]
31123118
(let [s (take n coll)]
31133119
(when (= n (count s))
31143120
(cons s (partition n step (drop step coll))))))))
31153121
([n step pad coll]
31163122
(lazy-seq
3117-
(when (seq coll)
3123+
(when-let [coll (seq coll)]
31183124
(let [s (take n coll)
31193125
ns (count s)
31203126
s (if (< ns n)
@@ -3151,7 +3157,7 @@
31513157
(partition-all n n coll))
31523158
([n step coll]
31533159
(lazy-seq
3154-
(when (seq coll)
3160+
(when-let [coll (seq coll)]
31553161
(cons (take n coll) (partition-all n step (drop step coll)))))))
31563162

31573163
(defn partition-by
@@ -3191,7 +3197,7 @@
31913197
(rf result elem)))))))))
31923198
([f coll]
31933199
(lazy-seq
3194-
(when (seq coll)
3200+
(when-let [coll (seq coll)]
31953201
(let [elem (first coll)
31963202
felem (f elem)
31973203
run (cons elem (take-while #(= felem (f %)) (next coll)))]
@@ -3216,7 +3222,7 @@
32163222
(let [coll-distinct (fn coll-distinct
32173223
[coll found]
32183224
(lazy-seq
3219-
(when (seq coll)
3225+
(when-let [coll (seq coll)]
32203226
(let [e (first coll)]
32213227
(if-not (contains? found e)
32223228
(cons e (coll-distinct (rest coll) (conj found e)))
@@ -3250,8 +3256,9 @@
32503256
(cons e (coll-dedupe (rest coll) e))
32513257
(coll-dedupe (rest coll) prev))))))]
32523258
(lazy-seq
3253-
(when-let [e (first coll)]
3254-
(cons e (coll-dedupe (rest coll) e)))))))
3259+
(let [coll (seq coll)]
3260+
(when-let [e (first coll)]
3261+
(cons e (coll-dedupe (rest coll) e))))))))
32553262

32563263
(defn flatten
32573264
"Flatten any combination of nested sequences (such as lists or vectors) into a single
@@ -3269,11 +3276,12 @@
32693276
(defn take-last
32703277
"Return the last ``n`` items in ``coll`` in linear time."
32713278
[n coll]
3272-
(loop [c (seq coll)
3273-
rem (seq (drop n coll))]
3274-
(if rem
3275-
(recur (next c) (next rem))
3276-
c)))
3279+
(let [coll (seq coll)]
3280+
(loop [c coll
3281+
rem (seq (drop n coll))]
3282+
(if rem
3283+
(recur (next c) (next rem))
3284+
c))))
32773285

32783286
(defn min-key
32793287
"Return the arg for which ``(k arg)`` is the smallest number. If multiple values

tests/basilisp/test_core_fns.lpy

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2453,6 +2453,92 @@
24532453
cat
24542454
(iteration range-chunk :somef (partial some #(< % 7)) :kf (comp inc last) :initk 0))))))
24552455

2456+
(def test-generator-vals [0 1 2 "three" nil 5])
2457+
2458+
(defn test-generator []
2459+
(dotimes [i (count test-generator-vals)]
2460+
(yield (nth test-generator-vals i))))
2461+
2462+
(deftest python-iterators-seq-fns-test
2463+
;; The plan here is to consume with each function the test generator
2464+
;; in its entirety, and check for missing values.
2465+
2466+
(testing "every?"
2467+
(let [nums* (atom [])]
2468+
(is (every? #(do (swap! nums* conj %)
2469+
(or (number? %) (string? %) (nil? %)))
2470+
(test-generator)))
2471+
(is (= test-generator-vals @nums*))))
2472+
2473+
(testing "some"
2474+
(let [nums* (atom [])]
2475+
(is (some #(do (swap! nums* conj %)
2476+
(= % 5))
2477+
(test-generator)))
2478+
(is (= test-generator-vals @nums*))))
2479+
2480+
(testing "map"
2481+
(is (= test-generator-vals (map identity (test-generator))))
2482+
(is (= ["00" "11" "22" "threethree" "" "55"] (map str (test-generator) (test-generator)))))
2483+
2484+
(testing "filter"
2485+
(is (= [0 1 2 5] (filter #(and (number? %) (> % -1)) (test-generator)))))
2486+
2487+
(testing "keep"
2488+
(is (= [0 1 2 "three" 5] (keep identity (test-generator)))))
2489+
2490+
(testing "keep-indexed"
2491+
(is (= [[0 0] [1 1] [2 2] [3 "three"] [4 nil] [5 5]] (keep-indexed vector (test-generator)))))
2492+
2493+
(testing "take"
2494+
(is (= test-generator-vals (take 6 (test-generator)))))
2495+
2496+
(testing "take-while"
2497+
(is (= test-generator-vals (take-while #(not= % 7) (test-generator)))))
2498+
2499+
(testing "take-while"
2500+
(is (= test-generator-vals (drop 0 (test-generator)))))
2501+
2502+
(testing "take-while"
2503+
(is (= [1 2 "three" nil 5] (drop-while #(not= % 1) (test-generator)))))
2504+
2505+
(testing "interpose"
2506+
(is (= [0 "-" 1 "-" 2 "-" "three" "-" nil "-" 5] (interpose "-" (test-generator)))))
2507+
2508+
(testing "interleave"
2509+
(is (= [0 0 1 1 2 2 "three" "three" nil nil 5 5] (interleave (test-generator) (test-generator)))))
2510+
2511+
(testing "cycle"
2512+
(is (= [0 1 2 "three" nil 5 0 1 2 "three"] (take 10 (cycle (test-generator))))))
2513+
2514+
(testing "take-nth"
2515+
(is (= [0 2 nil] (take-nth 2 (test-generator)))))
2516+
2517+
(testing "partition"
2518+
(is (= [[0 1] [2 "three"] [nil 5]] (partition 2 (test-generator))))
2519+
(is (= [[0 1] [1 2] [2 "three"] ["three" nil] [nil 5]] (partition 2 1 (test-generator))))
2520+
(is (= [[0 1 2 "three"] [nil 5 :pad :pad]] (partition 4 4 (repeat :pad) (test-generator)))))
2521+
2522+
(testing "partition-all"
2523+
(is (= [[0 1 2 "three"] [nil 5]] (partition-all 4 (test-generator))))
2524+
(is (= [[0 1 2 "three"] [nil 5]] (partition-all 4 4 (test-generator)))))
2525+
2526+
(testing "distinct"
2527+
(is (= test-generator-vals (dedupe (test-generator)))))
2528+
2529+
;; TODO
2530+
;; (testing "flatten"
2531+
;; (is (= nil (flatten [[:a :b :c] (test-generator)]))))
2532+
2533+
2534+
(testing "take-last"
2535+
(is (= [2 "three" nil 5] (take-last 4 (test-generator)))))
2536+
2537+
(testing "sort-by"
2538+
(is (= [5 nil "three" 2 1 0] (reverse (test-generator)))))
2539+
2540+
)
2541+
24562542
;;;;;;;;;;
24572543
;; Taps ;;
24582544
;;;;;;;;;;
@@ -2470,7 +2556,7 @@
24702556
a2-fn #(swap! a2-atom conj [:a2 %])
24712557
b-fn #(swap! b-atom conj %)]
24722558
(add-tap def-fn)
2473-
(remove-tap b-fn) ;; not an error
2559+
(remove-tap b-fn) ;; not an error
24742560
(tap> "this is a test")
24752561

24762562
;; Wait for the tap thread to drain

0 commit comments

Comments
 (0)