A possible solution would be to replace in the binding macro:
(push-thread-bindings (hash-map ~@(var-ize bindings)))
with
(push-thread-bindings (clojure.lang.PersistentHashMap/create ~(var-ize bindings))),
i.e. inline the hash-map call.
An additional improvement would be to make the call to hash-map at macro-expansion time:
(defmacro binding
"binding => var-symbol init-expr
Creates new bindings for the (already-existing) vars, with the
supplied initial values, executes the exprs in an implicit do, then
re-establishes the bindings that existed before. The new bindings
are made in parallel (unlike let); all init-exprs are evaluated
before the vars are bound to their new values."
{:added "1.0"}
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
(let [var-ize (fn [var-vals]
(loop [ret [] vvs (seq var-vals)]
(if vvs
(recur (conj (conj ret `(var ~(first vvs))) (second vvs))
(next (next vvs)))
(apply hash-map (seq ret)))))]
`(let []
(push-thread-bindings ~(var-ize bindings))
(try
~@body
(finally
(pop-thread-bindings))))))
The cause is probably that
spec-checking-fn
callswith-instrument-disabled
, which callsbinding
which expands in a call tohash-map
, so there's a loop. See https://github.com/clojure/clojure/blob/ee3553362de9bc3bfd18d4b0b3381e3483c2a34c/src/clj/clojure/core.clj#L1947.Repro:
A possible solution would be to replace in the
binding
macro:(push-thread-bindings (hash-map ~@(var-ize bindings)))
with(push-thread-bindings (clojure.lang.PersistentHashMap/create ~(var-ize bindings)))
, i.e. inline thehash-map
call.An additional improvement would be to make the call to
hash-map
at macro-expansion time:Benchmark:
With this fix
(hash-map 1 1)
works, but(hash-map 1)
doesn't yet.