Fork me on GitHub

Hi. I've noticed that CLJS impl of explain prints more stuff than Clojure. Is it on purpose? CLJS:

=>  (s/explain ::x 23)
val: 23 fails spec: :cljs.user/x predicate: string?
:cljs.spec.alpha/spec  :cljs.user/x
:cljs.spec.alpha/value  23
=>  (s/explain ::x 23)
val: 23 fails spec: :cljs.user/x predicate: string?


If I would like instrument to check my specs, what would be the preferred way of spec:ing a multimethod? Can I use a multispec with the same dispatch fn or do I need an indirection fn with a spec in each defmethod?

Alex Miller (Clojure team)11:06:48

You can make the defmulti dispatch function explicit and spec that


In my case each defmethod gets called with a map and the map should have different contents for each method. As I read your answer it would be the same spec for all methods?


@kenny I wonder if qualified symbols can be replaced like this:

(case form-sym
        cljs.spec.alpha/keys) ...

    (case form-sym
      `s/keys ...


given you already required [clojure.spec.alpha :as s]


then, getting rid of alpha would be just 1 line :require update


I recall that spec was inspired in part by RDF. Is there any recommended way for describing XML structures?

Alex Miller (Clojure team)14:06:34

xml represented by what data structure?


I'm using, so whatever that uses internally.


Its sexp-as-element is the closest I've seen it get to simple data structures, but even that seems to be pretty complex to spec

Alex Miller (Clojure team)14:06:38

seems pretty straightforward?


I'm afraid I don't follow

Alex Miller (Clojure team)14:06:41

there are at least two formats there - the input and output of sexp-as-element. they both seem pretty straightforward to spec if you want to


the output's, right?

Alex Miller (Clojure team)14:06:58

Element is a defrecord, so you can just spec it as a map with 3 known keys

Alex Miller (Clojure team)14:06:57

the sexp form is just structured vectors and can be spec’ed with s/cat etc

Alex Miller (Clojure team)14:06:10

oh, there actually are specs already in data.xml

Alex Miller (Clojure team)14:06:56

that’s for the element forms


it's not in the stable release yet though, is it?


i see you bumped its clojure dependency up to 1.9 when specs were introduced


as you pointed out i can just spec them as maps with :tag :attrs and :content


if I want to declare a with-gen ::spec generator-fn, generator fn needs to be a fn that returns a generator. how does one create a generator that’s simply a function, without using fmap or any of the other test.check.generators?


for example I just want a “generator” that invokes (random-uuid) where the fn itself is already random and doesn’t need any randomness from the generator scaffolding


i had some garbage like

(s/exercise ::p/id 10 {::p/id (fn [] (gen/fmap #(random-uuid) (s/gen (s/int-in 1 10))))})
but this is abusing fmap to just give me access to a fn I can call that will return a value that’s wrapped in the proper generator


maybe (gen/return .. ) ?


(gen/return (random-uuid)) maybe?


(def int-or-nil (gen/one-of [gen/int (gen/return nil)]))
(gen/sample int-or-nil)
;; => (nil 0 -2 nil nil 3 nil nil 4 2)


thats using gen/return to always return nil


I'm not entirely sure its what you are looking for though 😞


that seems like the same idea as abusing fmap and an existing gen (int-in), but with different fns. it just feels like there’s a built-in fn like gen/return for this use case, right?

Alex Miller (Clojure team)21:06:21

using external sources of randomness prevents shrinking and repeatability so is discouraged


if you want to do the discouraged thing, fmap will work and return won't.