core: move comparator/reductions/tree-seq to overlay (+ spec tests)

Sixth pure-fn batch (jolt-1j0 phase 2), 3 leaf fns, now with regression tests
per the per-batch workflow. reductions is the canonical form, so (reductions f [])
calls (f) -> [0] instead of the prior []; tree-seq is eager pre-order DFS.

conformance 228/228 x3, clojure-test-suite 3929, full suite green, bench A/B flat.
This commit is contained in:
Yogthos 2026-06-06 23:58:11 -04:00
parent c35cf7bdbc
commit 921b395dfd
3 changed files with 33 additions and 29 deletions

View file

@ -143,3 +143,28 @@
(defn undefined? [x] false)
(defn keyword-identical? [a b] (= a b))
(defn comparator [pred]
(fn [a b] (cond (pred a b) -1 (pred b a) 1 :else 0)))
;; Eager (Jolt has no laziness yet): a vector of the running accumulators.
(defn reductions
([f coll]
(let [s (seq coll)]
(if s
(reductions f (first s) (rest s))
(list (f)))))
([f init coll]
(loop [acc init xs (seq coll) out [init]]
(if xs
(let [a (f acc (first xs))] (recur a (next xs) (conj out a)))
out))))
;; Eager pre-order DFS (Clojure's is lazy; same order, fully realized here).
(defn tree-seq [branch? children root]
(let [walk (fn walk [acc node]
(let [acc (conj acc node)]
(if (branch? node)
(reduce walk acc (children node))
acc)))]
(walk [] root)))

View file

@ -1254,21 +1254,6 @@
(+= i n))
result))
(defn core-reductions
"(reductions f coll) or (reductions f init coll) -> seq of intermediate accs."
[f init-or-coll &opt maybe-coll]
(let [has-init (not (nil? maybe-coll))
coll (realize-for-iteration (if has-init maybe-coll init-or-coll))
result @[]]
(if has-init
(do (var acc init-or-coll) (array/push result acc)
(each x coll (set acc (f acc x)) (array/push result acc)))
(when (> (length coll) 0)
(var acc (in coll 0)) (array/push result acc)
(var i 1)
(while (< i (length coll)) (set acc (f acc (in coll i))) (array/push result acc) (++ i))))
(tuple/slice (tuple ;result))))
(defn core-dedupe [coll]
(let [c (realize-for-iteration coll) result @[]]
(var prev :jolt/none)
@ -3318,14 +3303,6 @@
(defn core-dorun [a & rest]
(let [coll (if (= 0 (length rest)) a (in rest 0))]
(realize-for-iteration coll) nil))
(defn core-tree-seq [branch? children root]
(def out @[])
(defn walk [node]
(array/push out node)
(when (truthy? (branch? node))
(each c (realize-for-iteration (children node)) (walk c))))
(walk root)
(tuple ;out))
# Map entries (represented as 2-element vectors)
# key/val require a map entry (a 2-element vector/tuple in Jolt); Clojure throws
@ -3385,8 +3362,6 @@
(defn core-promise [] (core-atom nil))
(defn core-deliver [p v] (core-reset! p v) p)
(defn core-comparator [pred]
(fn [a b] (cond (truthy? (pred a b)) -1 (truthy? (pred b a)) 1 true 0)))
(defn core-tagged-literal [tag form] @{:jolt/type :jolt/tagged-literal :tag tag :form form})
(defn core-ensure-reduced [x] (if (core-reduced? x) x (core-reduced x)))
(defn core-halt-when [pred & rest]
@ -3594,7 +3569,6 @@
"contains?" core-contains?
"count" core-count
"partition-all" core-partition-all
"reductions" core-reductions
"dedupe" core-dedupe
"keep-indexed" core-keep-indexed
"map-indexed" core-map-indexed
@ -3627,7 +3601,6 @@
"apply" core-apply
"doall" core-doall
"dorun" core-dorun
"tree-seq" core-tree-seq
"key" core-key
"val" core-val
"map-entry?" core-map-entry?
@ -3651,7 +3624,6 @@
"future-done?" core-future-done?
"future-cancel" core-future-cancel
"future-cancelled?" core-future-cancelled?
"comparator" core-comparator
"tagged-literal" core-tagged-literal
"ensure-reduced" core-ensure-reduced
"unreduced" core-unreduced

View file

@ -227,4 +227,11 @@
["replicate" "[:x :x :x]" "(replicate 3 :x)"]
["bounded-count" "3" "(bounded-count 3 [1 2 3 4 5])"]
["run! side effects" "6" "(let [a (atom 0)] (run! (fn [x] (swap! a + x)) [1 2 3]) @a)"]
["completing wraps rf" "3" "((completing +) 1 2)"])
["completing wraps rf" "3" "((completing +) 1 2)"]
["comparator <" "[1 2 3]" "(sort (comparator <) [3 1 2])"]
["comparator >" "[3 2 1]" "(sort (comparator >) [3 1 2])"]
["reductions" "[1 3 6 10]" "(reductions + [1 2 3 4])"]
["reductions with init" "[10 11 13 16]" "(reductions + 10 [1 2 3])"]
["reductions empty calls f" "[0]" "(reductions + [])"]
["reductions empty + init" "[5]" "(reductions + 5 [])"]
["tree-seq pre-order" "[[1 [2] 3] 1 [2] 2 3]" "(tree-seq sequential? seq [1 [2] 3])"])