core: Phase 4 — move reduce-kv to the overlay, fixing the vector case
reduce-kv is pure over reduce/keys/get/nth, so it moves to 20-coll with no host surface. Both branches fold through reduce, which fixes two latent bugs in the Janet version: on a vector it saw the pvec as a table and folded over its internal keys instead of the indices, and it ignored reduced entirely. nil folds to init. Added vector-index, reduced, and nil spec cases plus a 3-mode conformance case for the vector fix.
This commit is contained in:
parent
e6ff4b8a77
commit
fcdf0ff535
4 changed files with 16 additions and 8 deletions
|
|
@ -225,3 +225,14 @@
|
||||||
;; namespace-munge: Clojure namespace name -> legal Java package name (- -> _).
|
;; namespace-munge: Clojure namespace name -> legal Java package name (- -> _).
|
||||||
(defn namespace-munge [s]
|
(defn namespace-munge [s]
|
||||||
(apply str (map (fn [c] (if (= c \-) \_ c)) (seq (str s)))))
|
(apply str (map (fn [c] (if (= c \-) \_ c)) (seq (str s)))))
|
||||||
|
|
||||||
|
;; reduce-kv over a map (k v) or vector (index v). Both branches go through reduce,
|
||||||
|
;; so reduced short-circuits — and the vector path indexes correctly. (The prior
|
||||||
|
;; Janet version saw a pvec as a table and folded over its internal keys; it also
|
||||||
|
;; ignored reduced.) nil folds to init, matching Clojure.
|
||||||
|
(defn reduce-kv [f init coll]
|
||||||
|
(cond
|
||||||
|
(vector? coll) (reduce (fn [acc i] (f acc i (nth coll i))) init (range (count coll)))
|
||||||
|
(map? coll) (reduce (fn [acc k] (f acc k (get coll k))) init (keys coll))
|
||||||
|
(nil? coll) init
|
||||||
|
:else (throw (str "reduce-kv not supported on: " coll))))
|
||||||
|
|
|
||||||
|
|
@ -1296,13 +1296,7 @@
|
||||||
(defn cstep [i] (fn [] @[(in c (% i (length c))) (cstep (+ i 1))]))
|
(defn cstep [i] (fn [] @[(in c (% i (length c))) (cstep (+ i 1))]))
|
||||||
(make-lazy-seq (cstep 0))))))
|
(make-lazy-seq (cstep 0))))))
|
||||||
|
|
||||||
(defn core-reduce-kv [f init m]
|
# reduce-kv now lives in the Clojure collection tier (core/20-coll.clj).
|
||||||
(var acc init)
|
|
||||||
(cond
|
|
||||||
(phm? m) (each e (phm-entries m) (set acc (f acc (in e 0) (in e 1))))
|
|
||||||
(or (struct? m) (table? m)) (each k (keys m) (set acc (f acc k (get m k))))
|
|
||||||
(indexed? m) (do (var i 0) (each x m (set acc (f acc i x)) (++ i))))
|
|
||||||
acc)
|
|
||||||
|
|
||||||
# pop is defined only on stacks (vectors -> last end, lists -> front); Clojure
|
# pop is defined only on stacks (vectors -> last end, lists -> front); Clojure
|
||||||
# throws on sets/maps/seqs/strings/scalars. (peek lives in the Clojure kernel
|
# throws on sets/maps/seqs/strings/scalars. (peek lives in the Clojure kernel
|
||||||
|
|
@ -2765,7 +2759,6 @@
|
||||||
"keep-indexed" core-keep-indexed
|
"keep-indexed" core-keep-indexed
|
||||||
"map-indexed" core-map-indexed
|
"map-indexed" core-map-indexed
|
||||||
"cycle" core-cycle
|
"cycle" core-cycle
|
||||||
"reduce-kv" core-reduce-kv
|
|
||||||
"pop" core-pop
|
"pop" core-pop
|
||||||
"trampoline" core-trampoline
|
"trampoline" core-trampoline
|
||||||
"format" core-format
|
"format" core-format
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@
|
||||||
["subvec" "[2 3]" "(subvec [1 2 3 4 5] 1 3)"]
|
["subvec" "[2 3]" "(subvec [1 2 3 4 5] 1 3)"]
|
||||||
["subvec to-end" "[3 4 5]" "(subvec [1 2 3 4 5] 2)"]
|
["subvec to-end" "[3 4 5]" "(subvec [1 2 3 4 5] 2)"]
|
||||||
["reduce-kv" "{:a 2 :b 3}" "(reduce-kv (fn [m k v] (assoc m k (inc v))) {} {:a 1 :b 2})"]
|
["reduce-kv" "{:a 2 :b 3}" "(reduce-kv (fn [m k v] (assoc m k (inc v))) {} {:a 1 :b 2})"]
|
||||||
|
["reduce-kv vector idx" "(quote ([0 :a] [1 :b]))" "(reduce-kv (fn [a i v] (conj a [i v])) [] [:a :b])"]
|
||||||
|
|
||||||
### ---- iterating maps yields entries ----
|
### ---- iterating maps yields entries ----
|
||||||
["map over map" "true" "(= #{1 2} (set (map val {:a 1 :b 2})))"]
|
["map over map" "true" "(= #{1 2} (set (map val {:a 1 :b 2})))"]
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@
|
||||||
["reduce single no init" "5" "(reduce + [5])"]
|
["reduce single no init" "5" "(reduce + [5])"]
|
||||||
["reduced short-circuits" "3" "(reduce (fn [a x] (if (> a 2) (reduced a) (+ a x))) 0 [1 2 3 4 5])"]
|
["reduced short-circuits" "3" "(reduce (fn [a x] (if (> a 2) (reduced a) (+ a x))) 0 [1 2 3 4 5])"]
|
||||||
["reduce-kv" "6" "(reduce-kv (fn [a k v] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
|
["reduce-kv" "6" "(reduce-kv (fn [a k v] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
|
||||||
|
["reduce-kv on vector" "[[0 :a] [1 :b]]" "(reduce-kv (fn [a i v] (conj a [i v])) [] [:a :b])"]
|
||||||
|
["reduce-kv honors reduced" "[:a]" "(reduce-kv (fn [a i v] (if (= i 1) (reduced a) (conj a v))) [] [:a :b :c])"]
|
||||||
|
["reduce-kv on nil" "0" "(reduce-kv (fn [a k v] (+ a v)) 0 nil)"]
|
||||||
["reductions" "[1 3 6]" "(reductions + [1 2 3])"]
|
["reductions" "[1 3 6]" "(reductions + [1 2 3])"]
|
||||||
["mapcat" "[1 1 2 2]" "(mapcat (fn [x] [x x]) [1 2])"]
|
["mapcat" "[1 1 2 2]" "(mapcat (fn [x] [x x]) [1 2])"]
|
||||||
["keep" "[1 3]" "(keep (fn [x] (if (odd? x) x nil)) [1 2 3 4])"]
|
["keep" "[1 3]" "(keep (fn [x] (if (odd? x) x nil)) [1 2 3 4])"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue