Merge pull request #76 from jolt-lang/seed-shrink-r5-into-transduce
core: transduce/eduction/->Eduction to the overlay; into stays seed (perf wall)
This commit is contained in:
commit
5cac9efd4e
3 changed files with 39 additions and 26 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -1423,21 +1423,7 @@
|
|||
# :content) returned nil: janet keyword-apply is not jolt invoke). This
|
||||
# private composer remains ONLY for the transducer machinery below, where the
|
||||
# stages are always real fns.
|
||||
(def- td-comp
|
||||
(fn [& fs]
|
||||
(case (length fs)
|
||||
0 identity
|
||||
1 (fs 0)
|
||||
2 (let [f (fs 0) g (fs 1)] (fn [& args] (f (apply g args))))
|
||||
(let [f (last fs)
|
||||
gs (array/slice fs 0 (dec (length fs)))]
|
||||
(fn [& args]
|
||||
(var result (apply (last gs) args))
|
||||
(var i (- (length gs) 2))
|
||||
(while (>= i 0)
|
||||
(set result ((gs i) result))
|
||||
(-- i))
|
||||
(f result))))))
|
||||
# (td-comp is gone: eduction — its last caller — lives in the overlay now.)
|
||||
|
||||
# partial now lives in the Clojure collection tier (canonical arities).
|
||||
|
||||
|
|
@ -2416,14 +2402,7 @@
|
|||
(defn core-update-proxy [proxy mappings] proxy)
|
||||
# == lives in the Clojure collection tier (core/20-coll.clj); memfn is an
|
||||
# overlay macro (core/30-macros.clj) over the .method call sugar.
|
||||
(defn core-eduction [& args]
|
||||
# (eduction xform* coll): apply the composed transducers eagerly to coll
|
||||
(let [n (length args)
|
||||
coll (in args (- n 1))
|
||||
xforms (array/slice args 0 (- n 1))
|
||||
xform (if (= 0 (length xforms)) (fn [rf] rf) (apply td-comp xforms))]
|
||||
(core-into (make-vec @[]) xform coll)))
|
||||
(defn core->Eduction [xform coll] (core-into (make-vec @[]) xform coll))
|
||||
# eduction / ->Eduction live in the Clojure collection tier (core/20-coll.clj).
|
||||
(defn core-proxy-super [& args] (error "proxy-super: JVM proxies are not supported in Jolt"))
|
||||
(defn core-construct-proxy [c & args] (error "construct-proxy: not supported in Jolt"))
|
||||
(defn core-init-proxy [proxy mappings] proxy)
|
||||
|
|
@ -2508,6 +2487,8 @@
|
|||
@{:jolt/type :jolt/transient :kind :map :tbl t})
|
||||
# mutable-build arrays (vectors/lists) — copy into a transient vector
|
||||
(array? coll) @{:jolt/type :jolt/transient :kind :vector :arr (array/slice coll)}
|
||||
# tuples (reader vectors / map entries) are vectors too
|
||||
(tuple? coll) @{:jolt/type :jolt/transient :kind :vector :arr (array ;coll)}
|
||||
(error (string "Don't know how to create a transient from " (type coll)))))
|
||||
|
||||
# A transient is invalidated by persistent!; using it afterwards is a bug.
|
||||
|
|
@ -2705,7 +2686,6 @@
|
|||
"parse-double" core-parse-double
|
||||
"current-time-ms" core-current-time-ms
|
||||
"mapcat" core-mapcat
|
||||
"transduce" core-transduce
|
||||
"sequence" core-sequence
|
||||
"keyword" core-keyword
|
||||
"symbol" core-symbol
|
||||
|
|
@ -2817,8 +2797,6 @@
|
|||
"proxy-call-with-super" core-proxy-call-with-super
|
||||
"proxy-mappings" core-proxy-mappings
|
||||
"update-proxy" core-update-proxy
|
||||
"eduction" core-eduction
|
||||
"->Eduction" core->Eduction
|
||||
"proxy-super" core-proxy-super
|
||||
"construct-proxy" core-construct-proxy
|
||||
"init-proxy" core-init-proxy
|
||||
|
|
|
|||
|
|
@ -63,3 +63,15 @@
|
|||
["reduce empty calls f" "0" "(reduce + [])"]
|
||||
["reduce with-init" "16" "(reduce + 10 [1 2 3])"]
|
||||
["reduce reduced immediate" ":x" "(reduce (fn [a x] (reduced :x)) :init [1 2 3])"])
|
||||
|
||||
# into/transduce/eduction are overlay fns now (seed-shrink round 5): into
|
||||
# takes a transient fast path for vectors and preserves metadata; eduction
|
||||
# stays eager (documented divergence).
|
||||
(defspec "transducers / into & eduction (overlay)"
|
||||
["into list prepends" "(quote (4 3 1 2))" "(into (quote (1 2)) [3 4])"]
|
||||
["into sorted-map" "{1 :a, 2 :b}" "(into (sorted-map) [[2 :b] [1 :a]])"]
|
||||
["into from map entry" "[:a 1]" "(into [] (first {:a 1}))"]
|
||||
["into xform on map" "{:a 2}" "(into {} (map (fn [e] [(key e) (inc (val e))])) {:a 1})"]
|
||||
["eduction multiple xforms" "[4]" "(into [] (eduction (filter odd?) (map inc) [2 3 4]))"]
|
||||
["->Eduction" "[2 3]" "(->Eduction (map inc) [1 2])"]
|
||||
["transduce no init uses (f)" "5" "(transduce (map inc) + [1 2])"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue