core: move some/flatten/interleave/rationalize to overlay (+ spec tests)

Seventh pure-fn batch (jolt-1j0 phase 2), 4 leaf fns. flatten is the canonical
tree-seq form, which also flattens lists (sequential?) — the prior Janet impl's
seqish? predicate missed them. some/interleave eager; rationalize identity (no
ratio type).

conformance 228/228 x3, clojure-test-suite 3929 -> 3930 (flatten lists fix),
full suite green, bench A/B flat.
This commit is contained in:
Yogthos 2026-06-07 00:09:27 -04:00
parent 921b395dfd
commit fec5a10ccf
3 changed files with 35 additions and 34 deletions

View file

@ -59,6 +59,10 @@
(defn every-pred [& preds] (defn every-pred [& preds]
(fn [& xs] (every? (fn [p] (every? p xs)) preds))) (fn [& xs] (every? (fn [p] (every? p xs)) preds)))
(defn some [pred coll]
(when-let [s (seq coll)]
(or (pred (first s)) (recur pred (next s)))))
(defn some-fn [& preds] (defn some-fn [& preds]
(fn [& xs] (some (fn [p] (some p xs)) preds))) (fn [& xs] (some (fn [p] (some p xs)) preds)))
@ -168,3 +172,23 @@
(reduce walk acc (children node)) (reduce walk acc (children node))
acc)))] acc)))]
(walk [] root))) (walk [] root)))
;; Canonical flatten via tree-seq: the leaves (non-sequential nodes) in order.
;; Flattens lists too (sequential?), which the prior Janet impl missed.
(defn flatten [coll]
(filter (complement sequential?) (rest (tree-seq sequential? seq coll))))
;; Eager interleave (Clojure's is lazy): one from each coll in turn, until the
;; shortest ends.
(defn interleave [& colls]
(if (empty? colls)
(list)
(let [cs (mapv vec colls)
n (apply min (map count cs))]
(loop [i 0 out []]
(if (< i n)
(recur (inc i) (reduce (fn [o c] (conj o (nth c i))) out cs))
out)))))
;; No ratio type on Jolt, so rationalize is identity.
(defn rationalize [x] x)

View file

@ -1786,7 +1786,6 @@
(case (length a) (case (length a)
0 (rf) 1 (rf (a 0)) 0 (rf) 1 (rf (a 0))
(do (var acc (a 0)) (each x (realize-for-iteration (a 1)) (set acc (rf acc x))) acc)))) (do (var acc (a 0)) (each x (realize-for-iteration (a 1)) (set acc (rf acc x))) acc))))
(defn core-rationalize [x] x)
(defn core-random-sample [prob & rest] (defn core-random-sample [prob & rest]
(if (= 0 (length rest)) (if (= 0 (length rest))
(core-filter (fn [_] (< (math/random) prob))) (core-filter (fn [_] (< (math/random) prob)))
@ -3076,15 +3075,6 @@
(each x items (if first? (set first? false) (array/push r sep)) (array/push r x)) (each x items (if first? (set first? false) (array/push r sep)) (array/push r x))
(tuple ;r)))) (tuple ;r))))
(defn core-some-search
"(some pred coll) — first truthy (pred x), else nil."
[pred coll]
(def pred (as-fn pred))
(var result nil)
(each x (realize-for-iteration coll)
(let [r (pred x)] (when (truthy? r) (set result r) (break))))
result)
(defn core-keep (defn core-keep
"(keep f coll) — (f x) for each x, dropping nils. (keep f) is a transducer." "(keep f coll) — (f x) for each x, dropping nils. (keep f) is a transducer."
[f & rest] [f & rest]
@ -3096,25 +3086,6 @@
(let [v (f x)] (when (not (nil? v)) (array/push r v)))) (let [v (f x)] (when (not (nil? v)) (array/push r v))))
(tuple ;r)))) (tuple ;r))))
(defn core-interleave
"(interleave & colls) — take one from each in turn until the shortest ends."
[& colls]
(if (= 0 (length colls)) (tuple)
(let [cs (map realize-for-iteration colls)
n (min ;(map length cs))
r @[]]
(var i 0)
(while (< i n) (each c cs (array/push r (in c i))) (++ i))
(tuple ;r))))
(defn core-flatten
"(flatten coll) — fully flatten nested sequentials into one seq."
[coll]
(def r @[])
(defn seqish? [x] (or (tuple? x) (array? x) (pvec? x) (lazy-seq? x)))
(defn step [x] (each e (realize-for-iteration x) (if (seqish? e) (step e) (array/push r e))))
(when (seqish? coll) (step coll))
(tuple ;r))
(defn core-empty [coll] (defn core-empty [coll]
(cond (cond
@ -3660,10 +3631,7 @@
"random-uuid" core-random-uuid "random-uuid" core-random-uuid
"interpose" core-interpose "interpose" core-interpose
"mapcat" core-mapcat "mapcat" core-mapcat
"some" core-some-search
"keep" core-keep "keep" core-keep
"interleave" core-interleave
"flatten" core-flatten
"find" core-find "find" core-find
"transduce" core-transduce "transduce" core-transduce
"sequence" core-sequence "sequence" core-sequence
@ -3810,7 +3778,6 @@
"boolean" core-boolean "boolean" core-boolean
"cat" core-cat "cat" core-cat
"disj!" core-disj! "disj!" core-disj!
"rationalize" core-rationalize
"random-sample" core-random-sample "random-sample" core-random-sample
"reader-conditional" core-reader-conditional "reader-conditional" core-reader-conditional
"reader-conditional?" core-reader-conditional? "reader-conditional?" core-reader-conditional?

View file

@ -234,4 +234,14 @@
["reductions with init" "[10 11 13 16]" "(reductions + 10 [1 2 3])"] ["reductions with init" "[10 11 13 16]" "(reductions + 10 [1 2 3])"]
["reductions empty calls f" "[0]" "(reductions + [])"] ["reductions empty calls f" "[0]" "(reductions + [])"]
["reductions empty + init" "[5]" "(reductions + 5 [])"] ["reductions empty + init" "[5]" "(reductions + 5 [])"]
["tree-seq pre-order" "[[1 [2] 3] 1 [2] 2 3]" "(tree-seq sequential? seq [1 [2] 3])"]) ["tree-seq pre-order" "[[1 [2] 3] 1 [2] 2 3]" "(tree-seq sequential? seq [1 [2] 3])"]
["some found" "true" "(some even? [1 3 4])"]
["some none -> nil" "nil" "(some even? [1 3 5])"]
["some keyword pred" "7" "(some :a [{:b 1} {:a 7}])"]
["some returns value" "4" "(some (fn [x] (when (even? x) x)) [1 3 4 5])"]
["flatten nested" "[1 2 3 4 5]" "(flatten [1 [2 [3 4]] 5])"]
["flatten lists too" "[1 2 3]" "(flatten [1 (list 2 3)])"]
["flatten scalar -> empty" "[]" "(flatten 5)"]
["interleave" "[1 :a 2 :b]" "(interleave [1 2 3] [:a :b])"]
["interleave empty" "[]" "(interleave)"]
["rationalize identity" "5" "(rationalize 5)"])