From fec5a10ccf6b6b202412b1e32308d7ec31976697 Mon Sep 17 00:00:00 2001 From: Yogthos Date: Sun, 7 Jun 2026 00:09:27 -0400 Subject: [PATCH] core: move some/flatten/interleave/rationalize to overlay (+ spec tests) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- jolt-core/clojure/core/20-coll.clj | 24 ++++++++++++++++++++++ src/jolt/core.janet | 33 ------------------------------ test/spec/sequences-spec.janet | 12 ++++++++++- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/jolt-core/clojure/core/20-coll.clj b/jolt-core/clojure/core/20-coll.clj index 18c5dd5..8e6e21f 100644 --- a/jolt-core/clojure/core/20-coll.clj +++ b/jolt-core/clojure/core/20-coll.clj @@ -59,6 +59,10 @@ (defn every-pred [& 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] (fn [& xs] (some (fn [p] (some p xs)) preds))) @@ -168,3 +172,23 @@ (reduce walk acc (children node)) acc)))] (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) diff --git a/src/jolt/core.janet b/src/jolt/core.janet index 32a4352..daec67d 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -1786,7 +1786,6 @@ (case (length a) 0 (rf) 1 (rf (a 0)) (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] (if (= 0 (length rest)) (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)) (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 "(keep f coll) — (f x) for each x, dropping nils. (keep f) is a transducer." [f & rest] @@ -3096,25 +3086,6 @@ (let [v (f x)] (when (not (nil? v)) (array/push r v)))) (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] (cond @@ -3660,10 +3631,7 @@ "random-uuid" core-random-uuid "interpose" core-interpose "mapcat" core-mapcat - "some" core-some-search "keep" core-keep - "interleave" core-interleave - "flatten" core-flatten "find" core-find "transduce" core-transduce "sequence" core-sequence @@ -3810,7 +3778,6 @@ "boolean" core-boolean "cat" core-cat "disj!" core-disj! - "rationalize" core-rationalize "random-sample" core-random-sample "reader-conditional" core-reader-conditional "reader-conditional?" core-reader-conditional? diff --git a/test/spec/sequences-spec.janet b/test/spec/sequences-spec.janet index c85e6cc..1fee5b0 100644 --- a/test/spec/sequences-spec.janet +++ b/test/spec/sequences-spec.janet @@ -234,4 +234,14 @@ ["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])"]) + ["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)"])