Fork me on GitHub
#clojure-spec
<
2016-09-24
>
seancorfield00:09:23

@alexmiller I was just looking at https://github.com/clojure/clojure/commit/7ff4c70b13d29cf0a1fc7f19ba53413a38bb03d5 and noticed nonconforming which I had not previously seen in the API… and now it’s deliberately undocumented… I have several places where I have to conform with or and then use (conformer second) to "undo" the conformed result to get back what I need. Is there any likelihood that nonconforming would be "restored" to the documented API as something usable by developers? Or was it always intended to be an internal implementation detail and it just accidentally leaked?

alexmiller00:09:13

It was accidentally public and stands a good chance of being removed

seancorfield00:09:18

(I note that there actually is a test added in that commit for the nonconforming function, even tho’ that commit also removes it from the documentation)

alexmiller00:09:46

Well in my diligent way I added a test for the thing I fixed

ag00:09:26

guys… why when I have something like this:

(s/def ::mgen (s/with-gen
               (s/and not-empty map?)
               #(gen/map (s/gen ::keyword-with-question-mark) (s/gen boolean?))))

(gen/generate (s/gen ::mgen))
it would generate a map with multiple keys… but when used in prop/for-all always just a single key-value?

seancorfield00:09:39

Do you think "flattening" out an or is a good use case for having something like nonconforming tho’?

alexmiller00:09:05

But now that nilable doesn't use nonconforming Rich is considering removing it

alexmiller00:09:34

You can still easily do that with a conformer on val

seancorfield00:09:57

True, for a simple spec. It gets harder with more complex specs.

alexmiller00:09:11

Well, rely on it at your peril :)

seancorfield00:09:13

So far that’s the only case I’ve run into tho’, where I need s/or in order to combine specs but I really don’t want that branch in the result. (s/and (s/or :a ::some-pred :b ::other-pred) (conformer second)) seems a bit of a mouthful 😸

alexmiller00:09:35

@ag test.check is a bit different from spec in that spec wraps generators in a no-arg function - maybe that's causing the disconnect?

alexmiller00:09:46

@seancorfield: advice from us is: use conformers very sparingly

ag00:09:27

hmm… I still have no clue how to deal with that.

ag00:09:39

wrap into something like gen/fmap?

ag00:09:31

using overrides? second param of s/gen ?

alexmiller00:09:54

I don't totally understand what you're trying to do

ag00:09:25

I have a spec that generates a map (with gen/map), when used in gen/generate - it generates maps with multiple keys. but when used with test-check’s prop-all and quick-check it always generates maps with single key/value pair

alexmiller00:09:23

Hmm, not sure

seancorfield01:09:09

@alexmiller My use case — and it’s cropped up in a few specs I’ve needed at work — is that we have situations where we have some data that is either an X or a string that converts to an X (partly because of legacy constraints) but we want to conform the data to X in both cases and don’t care whether it was initially an X or a string.

seancorfield01:09:40

Now, you can certainly argue "Don’t do that!" but having it baked into the spec and being able to just (s/conform ::my-spec data) is nicer than having (if (string? data) …) everywhere that uses it.

plexus06:09:07

is this a bug or a feature?

plexus06:09:11

(s/valid? #{:clojure.spec/foo} :clojure.spec/foo) ;;=> true
(s/valid? qualified-keyword? :clojure.spec/foo) ;;=> true
(s/valid? #{:clojure.spec/invalid} :clojure.spec/invalid) ;;=> false
(s/valid? qualified-keyword? :clojure.spec/invalid) ;;=> false

seancorfield08:09:06

It's a feature. :clojure.spec/invalid is special -- it only ever satisfies s/invalid?.

mpenet08:09:08

Odd, seems like an impl. quirk

borkdude16:09:47

It would be nice if t/instrument also gave a warning when the :ret spec doesn’t conform. I know spec only tests this with t/check, but is there a reason the first one isn’t in spec (optionally) right now? Seems useful for dev purposes.

borkdude16:09:39

If I could programmatically insert a post-condition on a function that would get me far

alexmiller20:09:40

@borkdude: you can use s/assert to state postconditions if you like

alexmiller20:09:39

They can then be turned off and even optionally compiled out

borkdude20:09:08

@alexmiller ah yes, like in the snippet

jfntn21:09:57

If I have defined a spec for a value like :datomic/tempid, how can I reuse that in a map spec that’d say that the :db/id key should have a value that conforms to :datomic/tempid?

jfntn21:09:10

I think I got something usable! The point is that I want to define a map spec for an entity, and reuse that spec in describing the inputs to a tx and the outputs from a read. The trick is that the read and write specs should be identical with the exception that :db/id takes on different values

jfntn21:09:57

Not sure that’s a good way to do this, would appreciate some feedback

misha22:09:45

what am i doing wrong?

;; [org.clojure/clojure "1.9.0-alpha12"]
;; [org.clojure/clojurescript "1.9.229"]

=> (s/def :foo/bar
  (s/fspec :args
    (s/cat
      :id number?
      :type keyword?)))
:foo/bar

=> (s/spec :foo/bar)
#object[cljs.spec.t_cljs$spec32342]

=> (s/conform :foo/bar #(identity {}))
#object[TypeError TypeError: Cannot read property 'call' of undefined]

=> (s/explain-data :foo/bar '#(identity {}))
{:cljs.spec/problems [{:path [], :pred ifn?, :val (fn* [] (identity {})), :via [:foo/bar], :in []}]}

misha22:09:32

(I want to register a function spec to a keyword, to be able to "say" later: this map contains :foo/bar key, and its value is a function of 2 args: number and keyword)

misha22:09:22

or just to conform any other function to this function signature

misha23:09:15

=> (defn yoyo [f] (s/explain-data :foo/bar f))

=> (yoyo map)
#object[TypeError TypeError: Cannot read property 'call' of undefined]