Fork me on GitHub

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 ?


separate repo for shared specs works well


depends what it is


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.


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


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


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


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


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#]
      (cons '~m args#))))


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


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


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?


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


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


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


the clojure compiler doesn't do method splitting


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


@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


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.


And looking forward on progress on the CLJ-2112.


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.


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


functions as argument of instrumented fn get tested via gen yep


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


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


I've basically changed my spec from a useful fspec to just fn?. That'll do for now.