Fork me on GitHub
#clojure-spec
<
2016-11-22
>
paytonrules01:11:57

^Thanks for the help. I don’t think I said so properly before as my internet time was up.

yonatanel08:11:45

Is this anything to be worried about?

(s/conform (s/or) :anything)
=> :clojure.spec/invalid
(s/explain (s/or) :anything)
Success!
=> nil

yonatanel10:11:09

Here's my experiment in returning only the conformed value of an s/or spec:

(defmacro meat-grinder-or [& preds]
  (let [tags (map keyword
                  (repeatedly (count preds)
                              #(gensym "tag")))
        prepared (interleave tags preds)]
    `(s/and (s/or ~@prepared)
            (s/conformer val))))

Alex Miller (Clojure team)12:11:06

On the first question, that doesn't seem right, agreed. Feel free to log it if you like

yonatanel12:11:22

@alexmiller What do you mean by log it?

Alex Miller (Clojure team)13:11:50

No, sorry (it's on the list)

eggsyntax17:11:39

Is there an easy way to get the keys of a map spec pulled from the registry? I feel like there must be an obvious way I'm overlooking. I can just generate one & get the keys from that, but that feels inelegant (& might be incomplete if it had optional keys).

Alex Miller (Clojure team)17:11:53

you can use s/form to get the form version of it

Alex Miller (Clojure team)17:11:11

when we release form specs, you could then conform with that to extract the keys

Alex Miller (Clojure team)17:11:29

but you can work around that for the time being

eggsyntax17:11:44

Excellent. Thanks @alexmiller!

eggsyntax17:11:05

That's actually going to be broadly useful for me; I had overlooked s/form until now.

Alex Miller (Clojure team)17:11:41

there are a number of remaining issues with it and I have patches for most of those in the queue

Alex Miller (Clojure team)17:11:01

in particular all of the coll specs and keys* have broken forms atm

Alex Miller (Clojure team)17:11:22

and maybe conformer (can’t remember if that’s been applied yet)

eggsyntax17:11:44

OK, gotcha, I'll be cautious. Still, it's a great feature!

Alex Miller (Clojure team)17:11:33

those will all be fixed

zane19:11:09

Is there something I can read to better understand query caching and how to optimize queries?

seancorfield19:11:27

@zane Could you elaborate? That doesn’t sound related to clojure.spec...

zane20:11:47

That was indeed for the wrong channel.

zane20:11:51

Meant for #datomic.

zane20:11:11

Thanks for taking my question seriously anyway, @seancorfield. 😉

seancorfield21:11:15

@zane Ah, I wondered if it was for JDBC in which case I’d be happy to field it… in #clojure 🙂

rickmoynihan22:11:23

Does anyone have any tips on using clojure.spec to validate some data conforms to the spec in a clojure.test? Obviously I can do (is (s/valid? ::spec data) but if its invalid I want to see the explain output…

Alex Miller (Clojure team)22:11:15

we were waiting for you to do it

Oliver George22:11:41

Just a quick bit of feedback. This is a circular dependency thing. I generated some specs based on my relational database schema tables became (s/keys ...) fields became simple (s/def :schem.table/field pred) one-to-many relations became (s/def :schem.table/rel (s/coll-of :schem/table)) many-to-one relations became (s/def :schem.table/rel :schem/table)

Oliver George22:11:10

The slightly fiddly bit was the relations

Oliver George22:11:49

I couldn't dump these all in one file because the table specs needed to exist before the relation specs could be processed. (more specifically order mattered or it would throw an error)

Oliver George22:11:27

I was hoping all (s/def ...) statements were essentially lazy but perhaps that's not the case for performance reasons.

Oliver George22:11:42

I might need to produce a simple example to demonstrate this.

Oliver George22:11:39

(s/def ::a ::b) throws

CompilerException java.lang.Exception: Unable to resolve spec: :example.order-matters/b, compiling:(order_matters.clj:11:1) 

Oliver George22:11:45

My work around is to do all table defs first since they reflect relations. s/keys doesn't require the req/opt specs exist before the s/def

rickmoynihan22:11:59

@alexmiller: presumably the right thing to do is to extend assert-expr to operate on something like 'valid?

bfabry22:11:20

@olivergeorge I believe you can avoid that by doing (s/spec ::b)

bfabry22:11:03

although, that's not what the documentation says, so I'm probably confused

Oliver George22:11:36

Thanks @bfabry I did wonder if there might be something like that. I'll experiment more.

bfabry23:11:35

yeah actually doesn't work at all. my bad

Oliver George23:11:30

Actually this works: (s/def ::a (s/and ::b))

bfabry23:11:36

I wonder if there's a concise definition of which spec macros require definition and which don't

Oliver George23:11:55

Not sure I'd say neat exactly but it'll do the trick in my case.

Oliver George23:11:37

I'd be interested in hearing from @alexmiller if this is technically a bug or if "declare before use" is an implementation requirement/assumption

Oliver George23:11:59

@bfabry thanks for the inspiration 🙂

bfabry23:11:25

lol, glad to "help"

Alex Miller (Clojure team)23:11:35

I'd say bug, file a jira

Alex Miller (Clojure team)23:11:55

Everything should have delays, but there are a few places missing them

Oliver George23:11:04

Thanks Alex. Will do.

bfabry23:11:11

oh well that's concise enough, awesome

Alex Miller (Clojure team)23:11:01

That's either really easy to fix or really hard :)

Oliver George23:11:08

Logged. Please tell me if it's not a well formed JIRA ticket. http://dev.clojure.org/jira/browse/CLJ-2067

hiredman23:11:36

eventually @alexmiller will release a spec for jira tickets so you'll be able to s/valid? them before submitting them

rickmoynihan23:11:04

what do people think of this clojure.test extension for spec?

(defmethod assert-expr 's/valid? [msg form]
  (let [spec (second form)
        input-val (nth form 2)]
    `(let [value# ~form]
       (if value#
         (do-report {:type :pass, :message ~msg,
                     :expected '~form, :actual value#})
         (do-report {:type :fail, :message ~msg,
                     :expected (:clojure.spec/problems (s/explain-data ~spec ~input-val)), :actual ~input-val}))
       value#)))
Output looks like this:
FAIL in (foo-test) (common.clj:18)
expected: [{:path [],
            :pred (* :user/foo),
            :val "1",
            :via [:user/foo],
            :in []}]
  actual: "1"

Alex Miller (Clojure team)23:11:07

@olivergeorge good enough, I’ll tweak as needed