🐛 Fix deep-mapm double-applying mfn on leaf entries

The deep-mapm function was applying the mapping function twice on
leaf entries (non-map, non-vector values): once when destructuring
the entry, and again on the already-transformed result in the else
branch. Now mfn is applied exactly once per entry.
This commit is contained in:
Andrey Antukh 2026-04-14 20:04:36 +00:00 committed by Belén Albeza
parent a2e6abcb72
commit 057c6ddc0d
2 changed files with 12 additions and 12 deletions

View File

@ -602,12 +602,9 @@
(let [do-map
(fn [entry]
(let [[k v] (mfn entry)]
(cond
(or (vector? v) (map? v))
(if (or (vector? v) (map? v))
[k (deep-mapm mfn v)]
:else
(mfn [k v]))))]
[k v])))]
(cond
(map? m)
(into {} (map do-map) m)

View File

@ -538,17 +538,20 @@
(into [] (d/distinct-xf :id) [{:id 1 :v "a"} {:id 2 :v "x"} {:id 2 :v "b"}]))))
(t/deftest deep-mapm-test
;; Note: mfn is called twice on leaf entries (once initially, once again
;; after checking if the value is a map/vector), so a doubling fn applied
;; to value 1 gives 1*2*2=4.
(t/is (= {:a 4 :b {:c 8}}
;; mfn is applied once per entry
(t/is (= {:a 2 :b {:c 4}}
(d/deep-mapm (fn [[k v]] [k (if (number? v) (* v 2) v)])
{:a 1 :b {:c 2}})))
;; Keyword renaming: keys are also transformed — and applied twice.
;; Use an idempotent key transformation (uppercase once = uppercase twice).
;; Keyword renaming: keys are transformed once per entry
(let [result (d/deep-mapm (fn [[k v]] [(keyword (str (name k) "!")) v])
{:a 1})]
(t/is (contains? result (keyword "a!!")))))
(t/is (contains? result (keyword "a!"))))
;; Vectors inside maps are recursed into
(t/is (= {:items [{:x 10}]}
(d/deep-mapm (fn [[k v]] [k (if (number? v) (* v 10) v)])
{:items [{:x 1}]})))
;; Plain scalar at top level map
(t/is (= {:a "hello"} (d/deep-mapm identity {:a "hello"}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Numeric helpers