core: transduce/eduction/->Eduction to the overlay; into stays seed (perf wall)

Round 5 of the seed shrink. transduce is the canonical 5-liner over reduce
(which already honors reduced and steps lazy seqs); eduction composes with
comp and stays eager into a vector (documented divergence, as before);
td-comp — eduction's last caller — is deleted from the seed. transient
accepts tuples now (reader vectors / map entries), so (into [] (first {:a 1}))
keeps working everywhere a vector does.

into was moved, benched, and moved back: the overlay call layers cost the
into-vec suite ~11% back-to-back (536 vs 480ms), the same per-call wall that
sent even?/odd? home in round 4. A transient conj! fast path didn't pay for
itself either (jolt call overhead dominates, not the per-element conj). The
seed keeps core-into + its private transduce machinery; the binding count
still drops by three.
This commit is contained in:
Yogthos 2026-06-11 13:52:35 -04:00
parent b9c7a623bb
commit 2557e3295f
3 changed files with 39 additions and 26 deletions

View file

@ -967,3 +967,26 @@
(defn unchecked-char [x] (bit-and (int x) 0xffff))
(defn unchecked-float [x] (double x))
(defn unchecked-double [x] (double x))
;; --- transduce / into / eduction (seed-shrink round 5) ---------------------
;; Canonical transduce: build the stacked rf once, reduce (which honors
;; `reduced` and steps lazy seqs incrementally), then run the completion arity.
(defn transduce
([xform f coll] (transduce xform f (f) coll))
([xform f init coll]
(let [xf (xform f)]
(xf (reduce xf init coll)))))
;; into stays in the seed: it's perf-wall hot (the into-vec bench pays ~11%
;; through the overlay call layers — same lesson as even?/odd? in round 4).
;; eduction is EAGER on jolt (documented divergence, as before): the composed
;; xforms applied to coll, realized into a vector.
(defn eduction [& args]
(let [coll (last args)
xforms (butlast args)]
(if xforms
(into [] (apply comp xforms) coll)
(into [] coll))))
(defn ->Eduction [xform coll] (into [] xform coll))