Fork me on GitHub
#clojure-spec
<
2016-11-21
>
Alex Miller (Clojure team)00:11:51

@zane no, although that's been asked a lot

bbloom00:11:09

@alexmiller besides core, do you use a separate namespace for the separate file?

bbloom00:11:26

i guess yes if you want to load them with a require, no if you’re going to load them with load-file from the main ns?

Alex Miller (Clojure team)00:11:53

I think it's easier to use a separate ns

bbloom00:11:52

@alexmiller one weird thing with that, spec, and namespaced keywords in general, is that i find myself doing this:

bbloom00:11:05

(create-ns ‘mynamespace) (alias ‘m ‘mynamespace)

bbloom00:11:14

so that i can refer to things w/o a cyclic dep

Alex Miller (Clojure team)00:11:10

There is a patch I wrote to auto-create

Alex Miller (Clojure team)00:11:23

So just alias would be enough

bbloom00:11:28

that would be welcome

Alex Miller (Clojure team)00:11:30

Rich hasn't looked at it yet

bbloom00:11:36

¯\(ツ)

Alex Miller (Clojure team)00:11:39

Well, it's already screened, just waiting for a slice of rich time

bbloom00:11:58

not complaining - you know i’m in your camp on the processes 🙂

twashing01:11:38

and I’m hoping that such a useful function makes it into the core library.

Alex Miller (Clojure team)01:11:33

Not planning on it right now

bbloom04:11:43

i’m using spec in anger to solve a bug in an otherwise un-spec’d namespace right now

bbloom04:11:53

i haven’t found the bug i am looking for, but i did find three other lurking bugs

bbloom04:11:00

it’s kinda awesome.

twashing04:11:53

@alexmiller Curious as to why not. defspec-test, or something similar, seems to be low hanging fruit for adopting spec’d function tests, into a projects overall test suite.

kenny05:11:32

@twashing the one issue with the macro is it only counts generative tests as one test in the test summary (e.g. You run 1000 generative tests but the summary results only count it as one). I've been meaning to add it but haven't had time.

kenny05:11:07

If something like it isn't included in Clojure core when 1.9 is released then we can move it into a micro library instead of a gist

twashing06:11:14

@kenny Right, I was thinking just that. Kewl 👍

alqvist14:11:22

@kenny Would make may day if it found its way into 1.9

Alex Miller (Clojure team)14:11:36

in general, spec tests have a different shape than example based tests. I think it’s good to step back and think about why or if it’s valuable to force everything into the shape of something that clojure.test can run. This feels to me like the limits of our tool (particularly reliance on lein test to run and report everything) are affecting our ability to think about the problem. Why does there need to be only one kind of test runner? Why does there need to be only one kind of test? Generative tests are (by their nature) longer running and often don’t mix well with example based tests in a single suite. There is more to say on this.

bplatz15:11:25

Is there a way to use conform without destructuring the values? (i.e. I’d like have an s/or within the spec but not have change the original value).

Alex Miller (Clojure team)15:11:58

no, but you can use a conformer of val to undo conforming an or

Alex Miller (Clojure team)15:11:59

(s/and ::my-or-spec (s/conformer val))

Alex Miller (Clojure team)15:11:56

Rich toyed with s/nonconforming (still there but not in docs) but I suspect it will probably get removed before final release

dergutemoritz15:11:28

@bplatz You can fudge it by wrapping your or spec like this: (s/and (s/or ...) (s/conformer val))

dergutemoritz15:11:40

Though this is probably dangerously close to meat grinder territory again 😄

dergutemoritz15:11:03

Oops, sorry, I overlooked the first reply of yours @alexmiller

bplatz16:11:40

The use case here, which I’d think is a decent one, is validating and coercing JSON input - but downstream code expects data in a specific way.

bplatz16:11:39

Thanks for the s/and tip, I’ll use that for the time being until either it gets officially supported or we just use a different mechanism to coerce the data.

vikeri16:11:38

How does one go about speccing a multimethod? Can the different defmethods have different :args?

Alex Miller (Clojure team)16:11:58

I don’t think s/fdef works on multimethods right now

vikeri17:11:11

@alexmiller Ok, but if I don’t use multimethods but dynamically dispatches inside the function, can I somehow define a relation between the function arguments i.e.: > If the first argument is a number, then the second should conform to :c/myspec1 , but if the first argument is a keyword then the second argument should conform to :c/myspec2?

Alex Miller (Clojure team)17:11:32

there are a couple options

Alex Miller (Clojure team)17:11:03

one is to write an fdef with a :fn spec which can describe a relationship between args and ret

Alex Miller (Clojure team)17:11:25

another is to use s/multi-spec which can yield a different spec based on a separate multimethod

Alex Miller (Clojure team)17:11:57

the latter is really ideal for functions where the spec is open for extension after the fact

vikeri17:11:25

I checked into multi-spec, but then the input has to be a map right?

Alex Miller (Clojure team)17:11:31

I think there are examples of both in the guide http://clojure.org/guides/spec

Alex Miller (Clojure team)17:11:51

as long as you give it a multimethod that chooses the proper spec based on the input

vikeri17:11:45

@alexmiller Ah, just like multimethods the second argument is not a keyword but a function, but in clojure a keyword can be a function… Then that’s exactly what I need.)

Alex Miller (Clojure team)17:11:02

you will likely need a custom retag function too, but that’s not a big deal

Alex Miller (Clojure team)17:11:16

check the docstring for the details

paytonrules23:11:44

I have a clojure-spec/clojurescript question if anybody can help. I suspect it’s obvious.

paytonrules23:11:21

I have the following -

(s/def ::box (s/keys :req [::c/height ::c/width ::p/x ::p/y]))
(defn- right [box]
  (+ (:width box) (:x box)))

(defn- bottom [box]
  (+ (:height box) (:y box)))

(defn intersect? [box-one box-two]
  (not
    (or
      (> (::p/x box-two) (right box-one))
      (< (right box-two) (:x box-one))
      (> (:y box-two) (bottom box-one))
      (< (bottom box-two) (:y box-one)))))

(s/fdef intersect?
        :args (s/cat :box-one ::box :box-two ::box)
        :ret boolean?)

paytonrules23:11:59

What I can’t do is get the intersect? to actually assert when I call it incorrectly

paytonrules23:11:23

So for instance:

cljs.user=> (require '[cljs.spec :as s])
nil
cljs.user=> (s/check-asserts?)
true
cljs.user=> (box/intersect? {} {::c/width 100})
true

paytonrules23:11:51

I’m sure the problem is between brain and keyboard, but I’m pretty stumped. Shouldn’t this go kerblooie?

hiredman23:11:20

check-asserts? governs any s/asserts you have in the code, but you don't have any

paytonrules23:11:40

I thought fdef would instrument the function - thereby adding the asserts automagically

hiredman23:11:17

when testing you can run instrument, which turns on that sort of thing for testing, but you will also get bits of generative testing happening, so it is not something you generally want to turn on

bfabry23:11:54

@paytonrules you want to run (s/instrument)

paytonrules23:11:57

I was going by this from fdef docs

"Once registered, function specs are included in doc, checked by instrument,

paytonrules23:11:30

But apparently ClojureScript doesn’t have the instrument function

bfabry23:11:58

really? that surprises me

hiredman23:11:01

instrument is in clojure.spec.test (not sure what translation to that you need to do for clojurescript)

bfabry23:11:14

oh yeah, sorry, instrument is in a different ns

hiredman23:11:51

from what I understand, always on checking is a non-goal for spec

paytonrules23:11:51

Aha - it was the clojure.spec.test that I missed bit that I missed.

paytonrules23:11:35

Thanks a lot. It would appear then that spec’ing functions that you aren’t actively doing property based testing on, or debugging, may not be a useful endeavor.

bfabry23:11:07

@paytonrules I'm not sure that's true, I think there's still value in specing things and having instrumentation turned on for development/test

paytonrules23:11:14

I wonder how much slower things will be turning on instrument in development will be

bfabry23:11:45

unless you're getting into speccing function arguments I don't expect instrument will be super slow in a development context

paytonrules23:11:02

Maybe to turn it on and turn it off. I’m making an HTML5 game so if I spec everything it’ll hurt.

hiredman23:11:08

if you turn on instrument, invoking functions that are spec'ed will also cause those functions to be genertively tested against those specs

bfabry23:11:58

@hiredman I'm not sure that's right? I think it only generatively tests functions that you pass as arguments, to make sure the argument satisfies the fdef

bfabry23:11:20

user=> (defn foo []
  #_=>   (println "foo!"))
#'user/foo
user=> (s/fdef foo :args (s/cat) :ret nil?)
user/foo
user=> (clojure.spec.test/instrument)
[user/foo]
user=> (foo)
foo!
nil
user=>

hiredman23:11:54

the exact behavior is whatever, my point is, don't turn it on in production

hiredman23:11:05

you don't want to be running generative tests in production