Fork me on GitHub
#clojure-spec
<
2017-09-01
>
lmergen08:09:49

i have a question about project organisation and specs — specifically, i’ve settled on the use of a separate specs.clj file to put all my specs in, that works quite well. but, i have multiple small subprojects, of which some share the same specs (i.e. the output of one project is the input of another). what’s the best strategy here ? just copy/paste these common specs into these projects (because they’re different domains), or share the code using a common library ?

mpenet08:09:37

separate repo for shared specs works well

mpenet08:09:57

depends what it is

ikitommi09:09:06

could there be something like s/lazy which would work like s/spec but would not fail if the given qualified keyword doesn’t link to registered spec? could be used with the recursive specs (my example above). (s/lazy ::route) (vs (s/spec (s/and ::route)). The error messages be easier to understand. Happy to do a PR if.

wilkerlucio13:09:41

I have the same problem when trying to spec some distant relations where I can't guarantee the load order

wilkerlucio13:09:01

@ikitommi just one thing, you can do (s/and ::route) instead of (s/spec (s/and ::route)) and it will work the same

lmergen09:09:01

@mpenet in this specific instance it’s the spec of what a job input should look like — it’s produced by one component, and consumed in another.

lmergen09:09:37

so it strikes me that a common spec library might be a good approach for this, but it also feels like it might create more spaghetti / overhead

aisamu13:09:32

Hi! Is there a non-macro alternative to spec’s sequence operators? (`cat`, *, ? …). To avoid the XY problem: I have to generate medium-sized specs at “runtime”, and my current solution is giving me ERROR java.lang.RuntimeException: Method code too large!. I’ve read that it happens because there is an eval generating classes too big for the JVM. The eval exists because I couldn’t use the spec macros at runtime without wrapping them with make-fn. Is it unfeasible or just not currently implemented? Or am I approaching this backwards?

;; 
(defmacro make-fn [m] 
 `(fn [& args#]
    (eval 
      (cons '~m args#))))

ghadi14:09:47

@aisamu what specifically are you evalling that is causing the error?

aisamu14:09:39

The sequence macros, as in (make-fn s/?), which later gets called with apply and a vector of specs

dealy14:09:25

Hi, I've been trying to write a spec for a function which takes another function as a parameter. However it always fails with an Unable to construct gen error, is there a way to spec a function like this?

ghadi14:09:24

@aisamu Are you doing something like calling eval on a long collection [(s/?....)......] ? How many before it blows with an error?

aisamu14:09:34

@ghadi No. It's a small collection (~4), but the specs inside can get rather large. (The last input collection I managed to trace before the blow-up had 50k chars)

ghadi15:09:34

yeah... spec macros can generate a lot of code

ghadi15:09:55

the clojure compiler doesn't do method splitting

ikitommi15:09:47

@aisamu had the same problem. See the source code, most specs have non-documented functional versions beneath. Hopefully will be part of the final public api.

aisamu15:09:45

@ikitommi I looked into that, but it quickly became clear I'd have to bring along a dozen private functions to get the top level to work =/

Alex Miller (Clojure team)15:09:24

the downside of the functional versions is that you lose forms for reporting

Alex Miller (Clojure team)15:09:39

as those are captured by the macro

Alex Miller (Clojure team)15:09:16

I have talked here in the past about how specs for spec forms (CLJ-2112) can be used to programmatically construct specs via unform

Alex Miller (Clojure team)15:09:29

still a work in progress

ikitommi15:09:34

I don't mind that the forms need to be manually passed to the functions. I'm using a pred->form multimethod to auto-resolve the forms, with most/all core preds mapped.

ikitommi15:09:33

And looking forward on progress on the CLJ-2112.

hlship16:09:14

I think clojure.spec could do a bit better job of reporting failures to dynamically load clojure.test.check.generators. My production code doesn't include the org.clojure/test.check dependency, but does instrument a particular function at runtime; that seems to be forcing the code down a path that involves org.clojure/test.check ... possibly because some of the values being specs are functions? Very hard to say.

hlship16:09:43

Possibly this can be circumvented by providing an explicit generator for those function specs within our giant spec.

mpenet18:09:18

functions as argument of instrumented fn get tested via gen yep

mpenet18:09:37

you can overwrite :gen on them with ifn? but it kinda defeats the purpose after all, personally I would prefer if we could make it so that the argument (which is a fn) has its args checked at "invoke" time

mpenet18:09:53

there's also a ticket on hold somewhere about this if I recall

hlship19:09:39

I've basically changed my spec from a useful fspec to just fn?. https://github.com/walmartlabs/lacinia/pull/112 That'll do for now.