clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
johanatan 2020-09-02T04:16:33.033300Z

does anyone see why the following wouldn't work? I'm getting an error: sym not defined on the stest/check line.

(defn filtered-check [sym opts]
  (let [filter (or (.get (js/URLSearchParams. js/window.location.search) "filter") "")
        matches? (fn [s] (or (= filter "all")
                             (clojure.string/includes? (name s) filter)))]
    (when (matches? sym)
      (stest/check sym opts))))

johanatan 2020-09-02T04:25:02.033700Z

this is the exact error:

Unable to resolve symbol: sym in this context

  114  (defn filtered-check [sym opts]
  115    (let [filter (or (.get (js/URLSearchParams. js/window.location.search) "filter") "")
  116          matches? (fn [s] (or (= filter "all")
  117                               (clojure.string/includes? (name s) filter)))]
  118      (when (matches? sym)
  119        (stest/check sym opts))))
                          ^---

johanatan 2020-09-02T04:25:45.034600Z

it seems that stest/check may be a macro (I got "can't take value of macro" previously) but in the spec.alpha code it is defined as a function: https://github.com/clojure/spec.alpha/blob/master/src/main/clojure/clojure/spec/test/alpha.clj#L373

seancorfield 2020-09-02T04:39:07.035800Z

Perhaps it is a macro in ClojureScript?

seancorfield 2020-09-02T04:40:47.036200Z

Yup: http://cljs.github.io/api/cljs.spec.test.alpha/check it's a function in Clojure and a macro in ClojureScript.

seancorfield 2020-09-02T04:43:15.037Z

@johanatan You might have to ask in #clojurescript -- that seems an unfortunate and gratuitous difference in the implementations.

borkdude 2020-09-02T12:54:20.037500Z

I've also ran into this a couple of times

borkdude 2020-09-02T13:00:50.039100Z

I think the root of this lies in dynaload which is a macro in CLJS because requires are only possible at compile time (when not using a REPL). This implies that library code around check yields another macro. E.g. https://github.com/borkdude/respeced/blob/f5ff67aa78f588e7bad2a1b86dd1a646d3fdab3d/src/respeced/test.cljc#L81 and https://github.com/borkdude/respeced/blob/f5ff67aa78f588e7bad2a1b86dd1a646d3fdab3d/src/respeced/impl.cljc#L71.

johanatan 2020-09-02T16:54:05.040500Z

I suppose my best course of action is to succumb to macro contagiousness and make this a macro ?

borkdude 2020-09-02T17:44:31.040700Z

macros beget macros yeah

johanatan 2020-09-02T19:03:11.040900Z

🙂

johanatan 2020-09-02T21:17:44.042700Z

this is what i ended up coming up with (for anyone following along):

(defmacro filtered-check [sym opts]
  `(let [fltr# (or (.get (js/URLSearchParams. js/window.location.search) "filter") "")
         check# (fn [res#]
                    (cljs.test/is (= true (-> res# :clojure.spec.test.check/ret :result))
                        (goog.string/format "spec check failure:\r\n%s" (with-out-str (cljs.pprint/pprint res#)))))]
     (when (or (= fltr# "all") (clojure.string/includes? (name ~sym) fltr#))
       (let [check-res# (clojure.spec.test.alpha/check ~sym ~opts)]
         (clojure.spec.test.alpha/summarize-results check-res#)
         (if (nil? check-res#)
           (cljs.test/is false "stest/check result was nil. did you pass it any valid symbols?")
           (doall (map check# check-res#)))))))
you can use it with figwheel main to filter your stest/check calls:
location/figwheel-extra-main/auto-testing?filter=the_filter
and with your calls to the macro such as:
(macros/filtered-check ns/sym {:clojure.spec.test.check/opts {:num-tests N})

johanatan 2020-09-02T21:18:24.043100Z

[massive time saver once you start to accumulate many of these]