Fork me on GitHub
#clojure-spec
<
2017-07-04
>
dm310:07:48

how do you properly spec a structure where the contents depend on type of one of the fields? E.g.

(def m {:standard/source :the-source, :standard/content {:standard.content/details {... specific to :the-source ...}})
I’d like to make a spec for :standard.content/details based on :the-source

dm310:07:03

I can’t see the way out except for having :standard.content/details renamed to :the-source/details - is there any?

andrewmcveigh10:07:51

Sounds like a job for multi-spec

rickmoynihan11:07:28

is it just me or does (s/keys :req [(or ::foo ::bar)]) default generator always generate both ::foo and ::bar rather than one or the other, and both?

rickmoynihan11:07:32

I appreciate there are other ways to write this by moving the or over two keys specs

bronsa11:07:30

there's alraedy a ticket for this IIRC

danielstockton14:07:40

(s/def ::test (s/conformer (fn [q] q) (fn [q] (apply list q))))
(s/def ::test2 (s/map-of keyword? ::test))

(println (s/unform ::test [:a :b :c]))
(println (s/unform ::test2 {:some-key [:a :b :c]}))
The first unform works but not the second. Can anyone help?

rickmoynihan14:07:25

shouldn’t it be {::test [:a :b :c]}

rickmoynihan14:07:14

forgive me it’s map-of… seems strange then that it doesn’t work.

danielstockton14:07:25

I also tried (println (s/unform ::test2 (s/conform ::test2 {:test [:a :b :c]}))) just in case.

danielstockton14:07:02

Sorry, I'll rename that keyword to avoid confusion.

bronsa14:07:21

@danielstockton it's already been fixed in the latest spec version

danielstockton14:07:27

I'm on alpha17, has it been released?

bronsa14:07:31

try adding an explicit dependency to [org.clojure/spec.alpha "0.1.123"]

danielstockton14:07:41

Ok, will do, thanks.

bronsa14:07:50

altho I thought alpha17 depended on that

bronsa14:07:11

nevermind, this seems to be a different bug than the one I was thinking about (https://dev.clojure.org/jira/browse/CLJ-2076)

danielstockton14:07:45

It looks pretty similar.

bronsa14:07:07

ah yeah, it is. sorry, I tested on a broken repl

danielstockton14:07:44

Me too, I think I need cljs.spec

danielstockton14:07:42

Yes, I updated to the latest cljs and it works. Thanks!

danielstockton20:07:35

I think I may have found another bug in conform/unform:

(s/def ::join-key (s/or :prop keyword? :ident ::ident))
(s/def ::join (s/map-of ::join-key ::query))

(s/def ::query-expr
  (s/or :prop keyword?
        :join  ::join))

(s/def ::query
  (s/or :query (s/and (s/conformer #(if (vector? %)
                                      %
                                      :clojure.spec/invalid)
                                   list)
                      (s/+ ::query-expr))
        :not-query nil?))

(println (s/conform ::join {:a [:b]}))
(println (s/unform ::join (s/conform ::join {:a [:b]})))
Uncaught Error: nth not supported on this type cljs.core/Keyword
It seems to be due to ::join-key in map-of, if I replace that with keyword? then it works.

danielstockton20:07:01

Oh no, sorry. I need to read the documentation better. There is an option to conform keys for map-of.

danielstockton20:07:26

Perhaps it shouldn't throw an error though?

danielstockton20:07:57

If the key isn't conformed, unform could just return it as is.

jcf20:07:37

Hi all. Has anyone come up with an elegant way of specifying :args to a zero-arity function?

(s/fdef f
  :args empty? ; kinda cryptic, no?
  :ret map?)
empty? kinda does what I need I think because it'd end up applying an empty list of args to the function, but that seems a little cryptic.

jcf20:07:29

I guess I could use (s/coll-of any? :count 0) but again that doesn't sit well with me.

jcf20:07:23

Maybe I'll create ::none somewhere in my codebase to return an empty collection (s/coll-of any? :count 0 :into []).

jcf20:07:40

Or ::zero-args to make it clear what I'm doing.

jcf20:07:34

(s/def ::zero-args
  #{[]})
That works but I don't ❤️ it.