Fork me on GitHub
#clojure-spec
<
2019-01-26
>
borkdude15:01:38

hash-map can’t be instrumented and then called in CLJ but it can be in CLJS.

$ clj -A:test -m cljs.main -re node

ClojureScript 1.10.439
cljs.user=> (require '[speculative.core])
nil
cljs.user=> (require '[clojure.spec.test.alpha :as stest])
nil
cljs.user=> (stest/instrument `hash-map)
[cljs.core/hash-map]
cljs.user=> (apply hash-map [1])
repl:13
throw e__6573__auto__;
^

Error: Call to #'cljs.core/hash-map did not conform to spec.

$ clj -A:test

Clojure 1.10.0
user=> (require '[speculative.core])
nil
user=> (require '[clojure.spec.test.alpha :as stest])
nil
user=> (stest/instrument `hash-map)
[clojure.core/hash-map]
user=> (apply hash-map [1])
Execution error (StackOverflowError) at (REPL:1).
null

borkdude17:01:00

I don’t understand why, because this has never been the case before with CLJ. With CLJS these are pretty common, because it has no direct linking.

borkdude18:01:50

The cause is probably that spec-checking-fn calls with-instrument-disabled, which calls binding which expands in a call to hash-map, so there’s a loop.

borkdude19:01:48

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. Probably very low priority, but if there’s interest, I’ll make the JIRA ticket.

Alex Miller (Clojure team)21:01:58

Don’t want to depend on the class like that

Alex Miller (Clojure team)21:01:43

If anything would be better to use RT/map or whatever

borkdude22:01:23

RT/map is tricky, because then I need into-array which is not defined yet

borkdude22:01:09

When I depend on a local version of spec.alpha (not spec-alpha2), I get:

Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:382).
clojure.spec.alpha$explain_out
when I call an instrumented function with invalid args. No clue what this is.

borkdude22:01:50

When I install it with mvn it works

borkdude22:01:23

it seems like spec.alpha is AOT-compiled?