This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-10-09
Channels
- # aleph (9)
- # bangalore-clj (1)
- # beginners (3)
- # boot (58)
- # cider (19)
- # cljs-dev (5)
- # cljsrn (31)
- # clojure (35)
- # clojure-greece (1)
- # clojure-poland (4)
- # clojure-russia (1)
- # clojure-spec (65)
- # clojure-uk (1)
- # clojurescript (41)
- # data-science (2)
- # datascript (6)
- # devcards (3)
- # emacs (2)
- # hoplon (10)
- # liberator (3)
- # numerical-computing (1)
- # off-topic (1)
- # om (18)
- # onyx (17)
- # parinfer (1)
- # planck (1)
- # re-frame (13)
- # specter (7)
- # uncomplicate (1)
- # untangled (4)
- # vim (1)
- # yada (2)
I defined an fdef
spec for a macro and I’m testing it with (is (thrown? Exception (macroexpand ‘(my-macro bad-args))))
is your macro code actually being loaded? macroexpand doesn't throw an error if my-macro doesn't exist and isn't defined as a macro
the problem turned out to be related: it was loaded but not recognized by macroexpand
because I was not using a syntax-quote
Sometimes s/conform
and s/unform
are not inlined. For instance:
(s/def ::my-spec (s/cat :op (s/? (s/cat :a integer?))))
(->> (s/conform ::my-spec '(1))
(s/unform ::my-spec))
It returns ((1))
There is an extra nesting
Live demo here: http://bit.ly/2efyHkI
Is it a bug in clojure.spec
@alexmiller ?
is there a way to get a spec that (s/conform ::my-spec v)
will always conform to? I want to fspec
a function saying that it takes a spec-destructured value as an argument, and returns another spec-destructured value
did you try s/any?
?
I should rephrase, I want a specific spec that only accepts values in the shape that (s/conform ::my-spec v)
returns
Interesting question...
@viebel yes, generally anytime conform unform returns a different result, that's a bug. This particular one is already logged.
@sander no, other than saying what you just said as a custom predicate - call s/valid? on the result with another spec
Rich and I talked about this one on Friday in particular - it's tricky
Why is it tricky?
Conceptually tricky about what an optional regex should return in different contexts, how it nests, etc
In my specific case, I was able to workaround this bug using s/conformer
. But I still don’t understand fully how s/conformer
works. Could you explain in simple words how does s/conformer
work?
The docstring is a bit obscure...
It acts as a predicate but applies an arbitrary transformation in the conformed value
What is the simplest use case for conformer
?
Applying an arbitrary transformation to the conformed value
It is primarily a tool for building more complex spec variants
It's generally recommended to use sparingly as embedding it in a spec means that you are overriding how spec conforms for all future consumers of your spec
with s/and
?
Like if you used s/or but didn't want a tagged result
When you do that you throw away info about how something was conformed
One use might not need it but other possible future uses may
So baking it into your public spec takes away that option
I’ll play with that...
@alexmiller another use case would be when one wants to match regex with vectors
The naive code would be:
(s/def ::vec-of-int-and-str (s/cat :0 integer?
:1 string?))
(->> (s/conform ::vec-of-int-and-str [1 "a"])
(s/unform ::vec-of-int-and-str))
There will be a different solution for that
but it returns: (1 "a”)
instead of [1 “a”]
So the fix is:
(s/def ::vec-of-int-and-str (s/and
vector?
(s/conformer identity vec)
(s/cat :0 integer?
:1 string?)))
Is there a better solution for that?
Not yet but it's coming
I’m curious… ☺️
noob question, i’m sure, re: conformer - i reached for conformer when i was operating on data that looked like “123”, but i wanted (s/conform ::my-spec) to parse the integer such that it ended up being 123. what should i use instead of s/conformer in situations like that, for coercion of this sort?
i felt like i read about something that would solve this problem idiomatically in the rationale or guide, but couldn’t find it when i went back to look for it
@jrheard: yes I have a lot of cases where I have strings as input but I want them conformed to integers (for API input specs). But @alexmiller has told me a couple of times that is "not idiomatic" and to avoid conformers like that :(
hm, i don’t understand - the strings have to be turned into integers at some point, right?
is it more idiomatic to have a secondary, non-spec transformation layer that happens after s/conform?
i’m sure @alexmiller has good reasons for saying that, but i don’t understand what spec users are actually supposed to do here
The downside is that once you enshrine a conversion into your spec, you have made a conformance decision for all future consumers that has removed information. If you understand this ramification and are willing to live with the consequences, then that's up to you.
There are many ways to apply conversions - you should be aware of when you are conflating conformance and conversion though
i think i follow those statements, but a “in situations like that, try doing this instead” example would be supremely helpful 🙂
There's not one answer
You can apply post transformations
You can apply a second spec
You can apply a different spec in one case vs@another
And in some cases conformers might be the right answer