Fork me on GitHub

@alexmiller I was just looking at 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?


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


(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)


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


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?


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


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


You can still easily do that with a conformer on val


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


Well, rely on it at your peril :)


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 😸


@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?


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


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


wrap into something like gen/fmap?


using overrides? second param of s/gen ?


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


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


Hmm, not sure


@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.


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.


is this a bug or a feature?


(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


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


Odd, seems like an impl. quirk


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.


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


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


They can then be turned off and even optionally compiled out


@alexmiller ah yes, like in the snippet


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?


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


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


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
      :id number?
      :type keyword?)))

=> (s/spec :foo/bar)

=> (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 []}]}


(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)


or just to conform any other function to this function signature


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

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