Fork me on GitHub
#clojure-spec
<
2016-09-15
>
kenny00:09:04

Can you set the :default method for a multi-spec? Just adding a multimethod with :default for the dispatch value results in no method when calling explain. Small example:

(defmulti event-type :event/type)
(defmethod event-type :event/search [_]
  (s/keys :req [:event/type :event/timestamp :search/url]))
(defmethod event-type :default [_]
  (s/map-of any? any?))

(s/def :event/event (s/multi-spec event-type :event/type))
(s/explain-data :event/event
                {:event/type      :foo
                 :event/timestamp 1463970123000
                 :search/url      ""})
=> #:clojure.spec{:problems [{:path [:foo], :pred event-type, :val {:event/type :foo, :event/timestamp 1463970123000, :search/url ""}, :reason "no method", :via [:event/event], :in []}]}

hiredman00:09:16

it looks like no, because multi-spec re-implements the multimethod dispatch logic without :default

hiredman00:09:01

I suppose the default stuff would be tricky to handle well for generative testing

kenny00:09:59

Is there reasoning behind this?

kenny00:09:12

Behind not handling :default in defmethod ^

kenny00:09:32

Or has it just not been discussed?

Alex Miller (Clojure team)01:09:20

@kenny if :default doesn’t work, it should be made to

Alex Miller (Clojure team)01:09:37

at least as far as my thinking atm, so jira appreciated

Alex Miller (Clojure team)01:09:55

I did put a patch in alpha12 to make hierarchies work again, but I don’t recall testing :default stuff

kenny01:09:23

Oh shoot, I'm still on alpha11 because of the hash changes. I'll test it out in alpha12 and if it doesn't work I'll file a jira issue.

kenny01:09:03

@alexmiller Yes it is fixed in alpha12. Thanks!

curlyfry06:09:45

How "safe" am I in using spec in ClojureScript? Is it subject to any large changes in the future?

jmglov09:09:22

Any tips for writing a spec for the string version of a positive int? Here's what I'm doing now:

(defn- pos-int-string? [s]
  (try
    (pos-int? (Integer/parseInt s))
    (catch Exception _
      false)))

(s/def ::id pos-int-string?)

jmglov09:09:37

I assume that will need a custom generator though, right?

jmglov09:09:51

Any more idiomatic way to do it?

flipmokid11:09:38

Could spec be used to parse a vector such as '[1 + 3 * 4] and conform the input in such a way so that operator precedence is preserved?

jmglov14:09:16

The first time you see a function spec actually catching invalid input data is absolutely wonderful!

Alex Miller (Clojure team)14:09:28

@curlyfry spec is in alpha and subject to change (but probably unlikely to change dramatically, more additive)

jmglov14:09:22

Is there a way to use conform to drop all map keys not explicitly mentioned in an s/keys spec?

jmglov14:09:57

Let's say I have something like this:

(s/def ::foo string?)
(s/def ::bar int?)
(s/def ::thingy
  (s/keys :req-un [::foo]
          :opt-un [::bar])

Alex Miller (Clojure team)14:09:19

you could use something like (s/and (s/keys …) (s/conformer #(select-keys % #{::foo ::bar}))

jmglov14:09:57

I'd like to do this:

> (s/conform ::thingy {:foo "yup", :bar 42, :baz [1, 2, 3]})
{:foo "yup", :bar 42}

jmglov14:09:11

@alexmiller Wow! You guys thought of everything!

jmglov14:09:59

BTW, it is possible to run spec.test/check on a private function; my failure to do so was operator error. 🙂

Alex Miller (Clojure team)14:09:53

No one has filed an enhancement for that yeah afaik

Alex Miller (Clojure team)14:09:11

I'm not sure whether it should be supported or not

jmglov14:09:34

Well, it works. 🙂

jmglov14:09:04

(stest/check 'foo.bar/baz) is just fine, even if baz is defn-'d.

jmglov14:09:02

I personally think it should not be disallowed, since Clojure generally doesn't try too hard to save you from yourself with respect to "private" stuff in a namespace.

jmglov14:09:31

e.g. you can happily call a private function as long as you grab its var.

uwo18:09:22

how might I spec a map whose keys I do not know, but whose values all have the same shape?

uwo18:09:37

doh. thanks

richiardiandrea18:09:21

I have a little problem with this small test:

(defn all-divisions []
  {:test nil})

(s/fdef all-divisions
        :args empty?
        :ret #(do (log/error "here") (not (data-format/nil-keys? %))))

:: repl
(test/instrument `all-divisions) ;; => [app.db.queries/all-divisions]
(all-divisions) ;; => {:test nil}
Am I spec-ing it right? (I don't see "here" in the logs)

bfabry19:09:33

@richiardiandrea instrument does not check :ret or :fn

bfabry19:09:23

:ret and :fn are checked during clojure.spec.test/check checks though

richiardiandrea19:09:27

and what do I need to use to check :ret at runtime while developing ?

richiardiandrea19:09:57

tnx @bfabry I did not know that

richiardiandrea20:09:35

so if I want to instrument all the instrumentable symbols in my project, should I run! on instrumentable-syms the function instrument?

Alex Miller (Clojure team)20:09:17

No just call instrument with no args

Alex Miller (Clojure team)20:09:33

Also be aware of enumerate-ns

richiardiandrea20:09:40

@alexmiller cool, sorry it was right there in the docs

richiardiandrea20:09:07

reading through it now

smw22:09:59

oh my god… s/exercise is so cool.