Step 5: partition-by, dedupe → lazy overlay + trampoline/rand-int overlay
partition-by (10-seq.clj): ported canonical lazy implementation from CLJS — lazy-seq + cons + take-while, matching Clojure/CLJS exactly. Fixes the third and final remaining leak from Step 3. dedupe (20-coll.clj): replaced eager vec-based impl with lazy step function using lazy-seq + cons. Infinite input no longer hangs. trampoline (20-coll.clj): pure HOF ported from CLJS — recur until non-function result. Removed core-trampoline + binding from Janet. rand-int (20-coll.clj): thin overlay over Janet math/random + math/floor. Removed core-rand-int + binding from Janet. Removed core-partition-by + binding from core.janet (now in overlay). Tests: added dedupe infinite-input case to lazy-infinite harness. 22/22 pass. Conformance 229x3. Specs 32/32.
This commit is contained in:
parent
42da5cef9a
commit
64b1c60939
4 changed files with 37 additions and 31 deletions
|
|
@ -22,3 +22,15 @@
|
||||||
(if (next s)
|
(if (next s)
|
||||||
(recur (conj ret (first s)) (next s))
|
(recur (conj ret (first s)) (next s))
|
||||||
(seq ret))))
|
(seq ret))))
|
||||||
|
|
||||||
|
;; Lazy partition-by: groups consecutive elements by (f x), matching Clojure/CLJS.
|
||||||
|
(defn partition-by [f coll]
|
||||||
|
(let [step (fn step [s]
|
||||||
|
(lazy-seq
|
||||||
|
(let [s (seq s)]
|
||||||
|
(when s
|
||||||
|
(let [fst (first s)
|
||||||
|
fv (f fst)
|
||||||
|
run (cons fst (take-while (fn [x] (= fv (f x))) (rest s)))]
|
||||||
|
(cons run (step (lazy-seq (drop (count run) s)))))))))]
|
||||||
|
(step coll)))
|
||||||
|
|
|
||||||
|
|
@ -208,16 +208,32 @@
|
||||||
;; No ratio type on Jolt, so rationalize is identity.
|
;; No ratio type on Jolt, so rationalize is identity.
|
||||||
(defn rationalize [x] x)
|
(defn rationalize [x] x)
|
||||||
|
|
||||||
|
;; trampoline: repeatedly calls f with args until a non-function result.
|
||||||
|
(defn trampoline
|
||||||
|
([f] (trampoline f (f)))
|
||||||
|
([f & args]
|
||||||
|
(let [ret (apply f args)]
|
||||||
|
(if (fn? ret)
|
||||||
|
(recur ret)
|
||||||
|
ret))))
|
||||||
|
|
||||||
|
;; rand-int: random integer in [0, n). Uses Janet math/random.
|
||||||
|
(defn rand-int [n] (math/floor (* (math/random) n)))
|
||||||
|
|
||||||
;; Eager dedupe of consecutive equal elements (Jolt has no transducer arity yet).
|
;; Eager dedupe of consecutive equal elements (Jolt has no transducer arity yet).
|
||||||
(defn dedupe [coll]
|
(defn dedupe [coll]
|
||||||
(let [c (vec coll)]
|
(let [step (fn step [s prev]
|
||||||
(if (empty? c)
|
(lazy-seq
|
||||||
[]
|
(let [s (seq s)]
|
||||||
(loop [prev (first c) xs (rest c) out [(first c)]]
|
(when s
|
||||||
(if (seq xs)
|
(let [x (first s)]
|
||||||
(let [x (first xs)]
|
(if (= x prev)
|
||||||
(recur x (rest xs) (if (= x prev) out (conj out x))))
|
(step (rest s) prev)
|
||||||
out)))))
|
(cons x (step (rest s) x))))))))]
|
||||||
|
(let [s (seq coll)]
|
||||||
|
(if s
|
||||||
|
(cons (first s) (step (rest s) (first s)))
|
||||||
|
()))))
|
||||||
|
|
||||||
;; Internal helper for {:keys [...]} destructuring over a seq of k/v pairs:
|
;; Internal helper for {:keys [...]} destructuring over a seq of k/v pairs:
|
||||||
;; builds a map from consecutive pairs, dropping a trailing unpaired element.
|
;; builds a map from consecutive pairs, dropping a trailing unpaired element.
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,6 @@
|
||||||
(defn core-min [& args] (each x args (need-num x "min")) (apply min args))
|
(defn core-min [& args] (each x args (need-num x "min")) (apply min args))
|
||||||
|
|
||||||
(defn core-rand [] (math/random))
|
(defn core-rand [] (math/random))
|
||||||
(defn core-rand-int [n] (math/floor (* (math/random) n)))
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Comparison
|
# Comparison
|
||||||
|
|
@ -1318,21 +1317,6 @@
|
||||||
(+= i step))
|
(+= i step))
|
||||||
result))))
|
result))))
|
||||||
|
|
||||||
(defn core-partition-by [f coll]
|
|
||||||
(def f (as-fn f))
|
|
||||||
(var result @[])
|
|
||||||
(var part @[])
|
|
||||||
(var last-k nil)
|
|
||||||
(each x (realize-for-iteration coll)
|
|
||||||
(let [k (f x)]
|
|
||||||
(if (and last-k (deep= k last-k))
|
|
||||||
(array/push part x)
|
|
||||||
(do
|
|
||||||
(if (> (length part) 0) (array/push result (tuple/slice (tuple ;part))))
|
|
||||||
(set part @[x])
|
|
||||||
(set last-k k)))))
|
|
||||||
(if (> (length part) 0) (array/push result (tuple/slice (tuple ;part))))
|
|
||||||
result)
|
|
||||||
|
|
||||||
(defn core-partition-all [n coll]
|
(defn core-partition-all [n coll]
|
||||||
(if (lazy-seq? coll)
|
(if (lazy-seq? coll)
|
||||||
|
|
@ -1419,10 +1403,6 @@
|
||||||
|
|
||||||
# subvec lives in the Clojure kernel tier — core/00-kernel.clj.
|
# subvec lives in the Clojure kernel tier — core/00-kernel.clj.
|
||||||
|
|
||||||
(defn core-trampoline [f & args]
|
|
||||||
(var result (apply f args))
|
|
||||||
(while (function? result) (set result (result)))
|
|
||||||
result)
|
|
||||||
|
|
||||||
(def core-format (fn [fmt & args] (string/format fmt ;args)))
|
(def core-format (fn [fmt & args] (string/format fmt ;args)))
|
||||||
|
|
||||||
|
|
@ -2818,7 +2798,6 @@
|
||||||
"max" core-max
|
"max" core-max
|
||||||
"min" core-min
|
"min" core-min
|
||||||
"rand" core-rand
|
"rand" core-rand
|
||||||
"rand-int" core-rand-int
|
|
||||||
"=" core-=
|
"=" core-=
|
||||||
"not=" core-not=
|
"not=" core-not=
|
||||||
"<" core-<
|
"<" core-<
|
||||||
|
|
@ -2837,7 +2816,6 @@
|
||||||
"map-indexed" core-map-indexed
|
"map-indexed" core-map-indexed
|
||||||
"cycle" core-cycle
|
"cycle" core-cycle
|
||||||
"pop" core-pop
|
"pop" core-pop
|
||||||
"trampoline" core-trampoline
|
|
||||||
"format" core-format
|
"format" core-format
|
||||||
"first" core-first
|
"first" core-first
|
||||||
"rest" core-rest
|
"rest" core-rest
|
||||||
|
|
@ -2958,7 +2936,6 @@
|
||||||
"sort-by" core-sort-by
|
"sort-by" core-sort-by
|
||||||
"distinct" core-distinct
|
"distinct" core-distinct
|
||||||
"partition" core-partition
|
"partition" core-partition
|
||||||
"partition-by" core-partition-by
|
|
||||||
"range" core-range
|
"range" core-range
|
||||||
"repeat" core-repeat
|
"repeat" core-repeat
|
||||||
"iterate" core-iterate
|
"iterate" core-iterate
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
["take 6 mapcat dup range" "(quote (0 0 1 1 2 2))" "(take 6 (mapcat (fn [x] [x x]) (range)))"]
|
["take 6 mapcat dup range" "(quote (0 0 1 1 2 2))" "(take 6 (mapcat (fn [x] [x x]) (range)))"]
|
||||||
["first rest lazy" "1" "(let [[a & r] (range)] (first r))"]
|
["first rest lazy" "1" "(let [[a & r] (range)] (first r))"]
|
||||||
["take 3 rest lazy" "(quote (1 2 3))" "(let [[a & r] (range)] (take 3 r))"]
|
["take 3 rest lazy" "(quote (1 2 3))" "(let [[a & r] (range)] (take 3 r))"]
|
||||||
|
["dedupe inf" "(quote (1 2 1 2 1))" "(take 5 (dedupe (cycle [1 1 2 2])))"]
|
||||||
["take 3 take-nth 2 range" "(quote (0 2 4))" "(take 3 (take-nth 2 (range)))"]
|
["take 3 take-nth 2 range" "(quote (0 2 4))" "(take 3 (take-nth 2 (range)))"]
|
||||||
["take 3 interpose :x range" "(quote (0 :x 1))" "(take 3 (interpose :x (range)))"]
|
["take 3 interpose :x range" "(quote (0 :x 1))" "(take 3 (interpose :x (range)))"]
|
||||||
["take 3 map vector range iterate" "(quote ([0 100] [1 101] [2 102]))" "(take 3 (map vector (range) (iterate inc 100)))"]
|
["take 3 map vector range iterate" "(quote ([0 100] [1 101] [2 102]))" "(take 3 (map vector (range) (iterate inc 100)))"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue