Hah:
user=> (defn map?* [m] #?(:clj (instance? java.util.Map m) :cljs (map? m)))
#'user/map?*
user=> (merge {:a 1} (java.util.HashMap. {:b 2}))
{:a 1, :b 2}
user=> (associative? (java.util.HashMap. {:b 2})) ;; false
See: https://github.com/slipset/speculative/issues/70#issuecomment-435565720Other topic: I would say this is a blocking issue for speculative to upgrade to the new CLJS: https://github.com/slipset/speculative/blob/cljs-1.10.439/issues/callstack.cljs
(conj {:a 1} (java.util.HashMap. {:b 2}))
https://clojurians.slack.com/archives/C06E3HYPR/p1541196065067200
The messages after this seem quite promising.
I think it will be fun to collect the list of issues that were already found through the usage of speculative. If you still remember them, I’ll add them to a .md file 🙂
Not sure if you detected this one via the usage of speculative Mike: https://dev.clojure.org/jira/browse/CLJS-2945
and this one? https://dev.clojure.org/jira/browse/CLJS-2951
https://github.com/slipset/speculative/blob/master/doc/issues.md
When you want to upgrade to ClojureScript 1.10.439, Planck is ready. You can update these lines
https://github.com/slipset/speculative/blob/master/.circleci/config.yml#L43-L44
to specify 2.19.0-debian-9.0
(Homebrew versions of Planck are in the queue; until then brew install --HEAD planck
.)
@mfikes I’ll try in the cljs-1.10.439 branch in a minute
Planck made it through the homebrew and binaries are now available
Happy to open an issue for this question if that’s a better forum, but would you accept a PR that wraps popular predicates in a spec?
e.g. add (s/def ::fn ifn?)
and then replace every instance of ifn?
with ::ifn
The reason this would be useful is that it’s possible for other libs to put spec keywords into a registry and attach more info e.g. expound
Additionally, if spec ends up adding metadata, I’m guessing that will also be attached to the spec name https://dev.clojure.org/jira/browse/CLJ-2194
The downside would be a) an additional thing to remember when writing specs b) if this was non-idiomatic (not sure it is) then it could conflict with the goal of making it easy to convert “speculative” specs into “official” specs
the most concrete upside is that it would allow me to write code to present more beginner-friendly names for functions like ifn?
and seqable?
which can be pretty opaque if you’re just getting started
PR welcome!
I’ve already done this for ::pred, to indicate that the ifn in question should be a predicate.
@bbrinck there are already some examples of that. yesterday I added ::map-entry
About CLJS-2956. This is really a nasty problem in CLJS since a lot of spec code uses e.g. =
which causes =
instrumenting to be in a terribly high callstack, e.g. I measured 473 nestings.
Possible directions:
1) Count the nestings in spec-checking-fn
, if it’s a core fn we’re running and the nesting is too high, then call the raw function. I didn’t get this to work properly (yet) and it’s a hack only to get core spec’ing to work.
2) Use wrappers and pass them with :replace
:
(defn =-replace
([_] true)
([x y] (= x y))
([x & args]
(apply = x args)))
(defn =-test []
(stest/instrument `= {:replace {`= `=-replace}})
(println "yo")
(= 1 1))
With 2 we lose the ability to core self-checking, but this may even what we want in speculative, since then the performance loss of instrumenting isn’t that big. Maybe these replace wrappers could be automatically generated.
Scratch that, it also doesn’t work, unless you can get to the raw function in the wrapper.
Cool, so it’d be OK if I did a PR that extended that to, say, ifn?
and seqable?
among others?
Think so. I was contemplating a utils or predicates namespace, but maybe that’s premature.
Ok, well I’m happy to start a PR and we can adjust as necessary, as long as the general approach is consistent w the style so far. Thanks!
LOL, even getting to the raw function doesn’t help here.
(defn raw []
(:raw (get @@#'cljs.spec.test.alpha/instrumented-vars `=)))
(s/fdef clojure.core/=
:args (s/+ any?)
:ret boolean?)
(defn =-replace
([_] true)
([x y] ((raw) x y))
([x & args]
(apply (raw) x args)))
(defn wrong-call []
(= "a" "b"))
(t/deftest =-test []
(stest/instrument `= {:replace {`= `=-replace}})
(println "yo")
(= 1 1)
(wrong-call))
Spec now calls =-replace
internally where it used to call =
, so same loopI’m going to create an issue with this, mostly because then there is something to link to