This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-16
Channels
- # aws-lambda (10)
- # beginners (52)
- # boot (42)
- # cider (2)
- # cljs-dev (8)
- # cljsjs (4)
- # cljsrn (10)
- # clojars (3)
- # clojure (48)
- # clojure-conj (4)
- # clojure-dev (19)
- # clojure-italy (7)
- # clojure-norway (4)
- # clojure-russia (44)
- # clojure-spec (70)
- # clojure-uk (34)
- # clojurescript (39)
- # cursive (35)
- # data-science (11)
- # datomic (7)
- # emacs (6)
- # fulcro (2)
- # hoplon (12)
- # jobs (1)
- # juxt (18)
- # lein-figwheel (2)
- # leiningen (4)
- # luminus (9)
- # off-topic (29)
- # om (46)
- # onyx (131)
- # other-languages (24)
- # parinfer (84)
- # pedestal (10)
- # portkey (45)
- # protorepl (1)
- # re-frame (15)
- # reagent (43)
- # ring-swagger (41)
- # schema (6)
- # shadow-cljs (293)
- # slack-help (2)
- # specter (42)
I’ve seen cases like: - converting a string into a seq so spec regex operators can validate a string - converting a string into an int - converting a string into a UUID
But from my understanding of https://dev.clojure.org/jira/browse/CLJ-2116, conformers aren’t intended to be used for transformation
Are the above cases unintended uses of conformers? What would be an intended use case? I ask because I’m trying to figure out how to include support for conformers in Expound
the intended use case was for writing new composite spec types (like s/keys*)
so basically not what most people try to use them for
I think that while this might not have been the intended usage, it shows that there is a need here. I am having hopes that Rich will take this on as something to think about in the future.
For what it’s worth, using conformers in this way also makes it harder to give good error messages. I’m not sure what the best solution is, but perhaps two phases where first the data is validated, then transformed
to give you information about what you are validating for reuse "later", this makes more sense in the context of validating/destructuring data passed to a macro such as defn
Do you happen to have an example? My main source of examples of macros specs is https://github.com/clojure/core.specs.alpha, but I don’t see any conformers there
I am guilty of using it for transformation, not sure my example is clean but here you go: we have a dsl a bit like sql for a rule engine, we validate the syntax with spec and use a conformer to spill the ast (parsed form)
@mpenet Hm, that is interesting. Is the DSL originally a string then? Do you use spec to parse the string?
in reality it s a lot hairier because we have custom explain and whatnot but that s the idea
I see, thanks for the example. One reason it’s hard to add support for conformers is that a) I’m unclear on the intended use and b) in practice, it seems like they are often uses for transformation. I’m not sure if it’s practical to not support a common use case.
This is the part I don’t fully understand: conformers do transform values, but what are examples of recommended transformations? @alexmiller said: “I don’t think we are interested in turning spec into a transformation engine via conformers”, but I’m not sure what that includes/excludes
@mpenet In any case, I appreciate you explaining how you use them in practice. This is very helpful for my research, since I may end up wanting to support different use cases
the guide page intentionally does not mention conformers as we consider them to be primarily useful for writing new custom composite spec types (not for general data transformation)
By “composite spec types” do you mean new spec types that work similar to or
or regex specs? i.e. where I would want to name the parts?
Whoops, sorry I missed your comment addressing exactly this question in the thread above. Thanks!
@alexmiller would you be so kind to put an example of the “expected use” in
? 🙂
Currently only the “unintented use” is documented so I guess that this leads people in the wrong direction (and might continue to)
http://clojuredocs.org/clojure.spec/conformer
I think having a tool for transforming data informed by specs would be awesome. I don’t think conformers are that tool.
@alexmiller any ideas how could we find such a tool? It looks like we could do that with conformers, with just small changes to how it works. Or is there something new coming from Rich?
I'm trying to use spec to document a map that contains a :key-fn
that returns a collection
i.e. on this data {:aliases #{:bob :robert}}
, {:key-fn :aliases}
would be suitable.
However this happens
(s/def ::key-fn
(s/fspec :args (s/cat :item any?)
:ret (s/coll-of any?)))
(s/def ::my-map (s/keys :req [::key-fn]))
(s/valid? ::my-map {::key-fn :aliases}) ;;false
(s/valid? ::key-fn :aliases) ;; false
Am I doing this all wrong?hmm I did try (s/valid? ::my-map {::key-fn (fn [x] [:a :b])}) ;;false
and got the same thing though
the thing is it's the fact that the function returns a collection that is the important thing I'm trying to capture
I wouldn't mind if I have to help it along with a generator or something
but I don't know where or how or if I'm approaching the whole thing in a stupid way
oh no wait
the inlined function with constants worked
I would like to specify that if you're gonna give a keyword it's got to look up data that is a collection
hmm maybe need another approach if you need that guarantee… a keyword could return anything that happens to be in the map
mm yes
as far as I can make out specifying the return types of functions <as> parameters is a bit of an edge case
but would love to be able to provide it to help readers understand the contract
so I guess you’d need more context if you were going to validate that the supplied keyword would return a collection; you’d need to know 1) what the keyword is and 2) the value for that keyword in the other map it’d be applied to?
yeah you're right
I suppose I could just put it in the doc string
one weird idea: if you had all this info (including the “subject” map) in one data structure, you could write a spec for the whole structure to ensure any ::key-fn
refers to a collection value in the “subject” map
ooh interesting
Anyway, the return value spec for your function isn’t going to matter for valid?
. It’d be useful if you were using test.check to check the function though
Is there a way to write a spec that checks properties of pairs of elements in a sequence? E.g. in [{:a 1 :b 2} {:a 2 :b 3} {:a 3 :b 4}]
I’d like to check that :b
is equal to :a
for each pair of items from the sequence.
But then on failure explain returns the entire sequence as the value causing the problem.
Do you mean there is some relationship between adjacent maps? or within individual maps?
I mean that for {:a 1 :b 2}
and {:a 2 :b 3}
:b
of the first and :a
of the second must match, and then for {:a 2 :b 3}
and {:a 3 :b 4}
, we have the same check and so on
You can individually check pairs by running (map #(s/valid? ....) (partition 2 1 collection))
otherwise you can continue to check the whole collection and get errors at the collection level