Fork me on GitHub
#clojure-spec
<
2016-08-15
>
lvh02:08:04

Reminder: https://github.com/gfredericks/schpec exists and you might like it and it could use some eyeballs 🙂

lvh02:08:44

I’ll probably end up contributing regex-str spec at some point because I gotta write it anyway

lvh02:08:13

What would be an appropriate name for a spec for a string that matches a regex?

gfredericks02:08:13

Would re-matches and re-find be weird?

lvh02:08:41

My first attempt was matches-re?

lvh02:08:16

I wonder how I’d write the generator for has-re? or whatever; so far I only care about the entire re

lvh02:08:48

I guess I could generate prefix string, re string, suffix string in parallel and then fmap str/join

lvh02:08:08

huh, with-gen has a branch for if the spec is a regex

lvh02:08:41

oh, wait, that means clojure.spec generalized regex, not str regex 🙂

sandbags09:08:41

Perhaps this is obvious but I just noticed that cljs.spec doesn’t seem to define an assert macro a la clojure.spec

sandbags09:08:59

seems relatively unlikely to be an oversight so I am wondering what I am missing

sandbags09:08:48

I guess i can provide my own version of assert*

brabster10:08:53

If I want to always validate a function's input against an fdef spec, do I need to use the clojure.spec.test namespace? Or does the namespacing suggest that eg. clojure.spec.test/instrument is only for use in development and tests and I shouldn't use it otherwise?

borkdude10:08:27

@brabster: Maybe you can separate out the args spec and refer to it in the fdef - and then call s/valid? in your function (or hook it up with :pre)?

brabster10:08:13

@borkdude: you're right, I did that but it's quite a lot of extra typing if the individual arg specs aren't really reusable anywhere - and when I use a spec in a precondition the error message doesn't give any details of why the validation failed (just gives the name of the spec)

brabster10:08:39

plus I seem to frequently end up with what feels like duplication like (s/cat :foo ::foo :bar ::bar :baz ::baz) when I break the specs out - maybe i'm just writing bad clojure or something 🙂

brabster10:08:24

(tbh I'm struggling a little to work out when/when not to use namespaced keywords too :P)

borkdude10:08:38

It's quite annoying to get the arguments as a vector that you can validate yourself, isn't it?

borkdude10:08:17

without repeating

borkdude10:08:45

Say we have:

(s/def ::my-fn-args (s/cat :n number? :s string?))
(s/fdef my-fn :args ::my-fn-args)
(defn my-fn [n s] (if (s/valid? ;; now what?

borkdude10:08:59

I get your point. Following the discussion.

borkdude10:08:38

What I'm also a bit uneasy with is that you have to repeat the argument names and that there's a possible source of duplication error.

brabster11:08:28

I imagine there are plans to integrate spec more deeply with core stuff like defn so maybe this is a bit painful because it's early days

borkdude11:08:47

It would be cool if you could write a spec and then the function using the spec:

(defn my-fn ::my-fn-args ...)
Kind of like that.

brabster11:08:13

Looks good to me

brabster11:08:02

With the option to disable at runtime if you want to trade off the safety for slightly faster code

brabster11:08:59

What might be even nicer is combined spec conform and destructuring if that's possible

brabster11:08:44

Thanks for the input @borkdude, more confident I'm not missing something really obvious now 🙂

borkdude11:08:24

@brabster: No problem, I'm also just beginning to see the dimension that spec adds to Clojure. Pretty excited about it.

Ed15:08:46

@borkdude: seems really useful ... maybe it should do the conform so you specify something like (defn my-fn [{:keys [destructuring form]} ::my-fn-args] ...) and you could get the destructured pieces in your arguments?

borkdude15:08:37

I don't know yet, but something with less boilerplate would be awesome

borkdude15:08:48

(defn my-fn #[n number? :s string?] ...)  
without having to destructure vs
(defn my-fn [{:keys ....]] (s/cat :n number? :s string?) ...)

borkdude15:08:30

don't know if it makes sense 🙂

brabster16:08:58

looks like a good start on the idea to me!

borkdude16:08:30

Is it possible to get the keys out of an s/cat without using exercise?

Alex Miller (Clojure team)16:08:32

you can call s/form and grab the odd elements

Alex Miller (Clojure team)16:08:58

(->> (s/cat :a string? :b keyword?) s/form (drop 1) (partition-all 2) (map first))

arohner19:08:52

borkdude: if you’re doing serious parsing, you may also want to look at spectrum:

arohner19:08:25

spectrum.conform/parse-spec returns defrecords for the vast majority of specs. 100% coverage is a goal

burbma21:08:19

Having an error specing a function that takes a seq of maps. Here’s a gist with a cljc and error. https://gist.github.com/mmb90/e2e33cb526ed8c25549edbdb6e48f711

burbma21:08:30

It seems to think it should be getting a map instead of a seq of maps. Is there a detail I’m missing?

seancorfield23:08:19

@mmb90: s/* is a regex for zero or more of these specs — so you’re saying name-unicorns takes zero or more arguments, each of which should match the ::unicorn spec.

seancorfield23:08:43

I think you want s/coll-of for a collection of ::unicorn entities.

smniel23:08:07

@seancorfield: The s/* is inside of an s/cat pulling out the first argument, so I thought the spec said that name-unicorns takes one argument which is a sequence of zero or more ::unicorns entities.

seancorfield23:08:54

The s/cat is for the entire :args sequence.

seancorfield23:08:31

In s/fdef you specify :args as a sequence — as if you always invoked the function with apply.

smniel23:08:10

Yes. I understood that aspect, but I didn’t understand the way s/cat and s/* were combining to only specify one sequence. I was understanding as if the s/* were wrapped in s/spec which is required to turn a regex-op into a full spec or predicate.

smniel23:08:18

Does that sound correct?