This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-18
Channels
- # architecture (25)
- # beginners (57)
- # boot (3)
- # cider (38)
- # clara (6)
- # cljsrn (6)
- # clojure (54)
- # clojure-china (4)
- # clojure-greece (1)
- # clojure-italy (3)
- # clojure-romania (1)
- # clojure-russia (7)
- # clojure-spec (68)
- # clojure-uk (46)
- # clojurescript (73)
- # community-development (2)
- # core-async (7)
- # cursive (17)
- # datomic (143)
- # duct (2)
- # emacs (12)
- # events (5)
- # figwheel (3)
- # fulcro (15)
- # hoplon (19)
- # jobs (12)
- # jobs-discuss (85)
- # nginx (3)
- # off-topic (111)
- # onyx (7)
- # other-languages (1)
- # re-frame (30)
- # reagent (19)
- # remote-jobs (1)
- # ring (7)
- # rum (1)
- # shadow-cljs (18)
- # spacemacs (4)
- # specter (4)
- # sql (24)
- # test-check (1)
- # unrepl (10)
- # vim (6)
- # yada (1)
In Clojurescript, what are people doing if they want to remove spec from production builds? Is there a lib for it? Macros wrapping fdef in the same file? Or placing all spec stuff in a dev-only namespace?
Download size
If I’m only validating/testing with spec, I don’t want it to take up sie in the resulting Js artifact
Thx @borkdude. Thing is, I prefer fdefs
be defined by their function, so I was hoping someone had already handled this. We have some dev-time-only logging macros I could repurpose… though I suspect dev-only namespaces would still be tricky, assuming it’s even possible
@kingmob this project has an example how dev only namespaces are possible (both lein and boot): https://github.com/borkdude/lein2boot
yeah it would be nice if you could elide all spec related stuff under advanced compilation
@borkdude Ahh, it looks like you factored out everything common into its own file and then use different :source-paths
. We do that, too, but if, e.g., I added fdef
s in animals.crud
, they’d still end up in prod builds
We could add it to the dev source path, but then it’s separate from the definition…which is fine, it’s not really that big a deal
have you tried what difference in size you get for the production js with and without? it may not even be worth it
@dpsutton Yeah, it would be nice. Does spec use asserts
under the hood so that the :elide-asserts
option would remove it?
@borkdude Yeah, I have actually, it’s substantial 🙂 Lemme recompile and check with source-map-explorer again
@borkdude OK, bare-bones spec is adding 39.84 kb to the output .js. It’s not major, but this is just for spec itself, and a sprinkling of initial spec defs. It’s not extensive at all, and since none of it is used at run-time, we might as well ditch it.
I see there is an issue about it: https://dev.clojure.org/jira/browse/CLJS-1701
I've been thinking about building some company/app wide specs. Say I spec something as :com.myco.app.service/id
- is there any way that I can apply that spec to some data where everything is named as :service/id
?
(s/def :service/id :com.myco.app.service/id)
?
(and then use that local "alias")
Oh I didn't think of that - thanks!
is there something like this in spec?
(defn conform! [spec thing]
(if (s/valid? spec thing)
thing
(throw (ex-info (s/explain-str spec thing)
(s/explain-data spec thing)))))
Sounds like s/assert
to me @schmee?
Also, I'd note that your function does not conform the value so it's a very misleading name...
Perhaps
(defn conform! [spec thing]
(let [v (s/conform spec thing)]
(if (s/invalid? v)
(throw (ex-info ...))
v)))
(whereas s/assert
returns the original thing
, not the conformed value)
yeah, I copied my conform thing from another project where I needed the conformed value, now I just want to validate so s/assert
is perfect :thumbsup:
Just bear in mind it can be turned on/off by command line options and by code (including 3rd party libraries!).
(and asserts can be turned on/off by calling code via *assert*
)
so, when s/keys fails on a missing required key, there’s no path information in explain-data
. We’re attempting to dispatch on the result of explain-data, but the information we need about the missing key is in a :pred function. So is the only way to parse this data to parse the s expression used internally to describe required keys?
@uwo Yeah, that's ugly. We wrote a heuristic-based explain-data walker to figure that stuff out. It recognizes and picks apart the :pred
value...
Off the top of my head, nope, sorry.
But we needed to pick apart spec errors in general and map them back to our domain for reporting to end users... it just took us a while to flesh out the walker (it's... non-trivial).
how do you go about spec-ing anonymous functions with side-effects? since conform
et al actually calls the function it’s validating, I guess the answer is “don’t do it?”
Not sure what situation you're talking about @schmee?
I have a piece of code that takes an array of functions, and those functions should return a particular type of record
I call s/valid?
on the input to this code, and if I use fspec
to check the functions in the array, it will actually call all those fns to ensure that they return the correct thing
but those fns could grab values from a database, launch nuclear missiles or whatever, so I’m thinking I should just spec it as (s/+ fn?)
instead
Yes, best not to use fspec
for side-effecting functions-as-arguments because instrumentation uses generative testing on them.
Use ifn?, not fn?
An array of functions sounds more like (s/coll-of ifn?)
+ is a regex op used for describing the internal structure of sequential collections (like an arg list). coll-of is for sequential collections. Either may be applicable here, depends on context.
In particular, what if anything is including this spec
If, for example, you’re including it as one arg in an args spec, using + would be bad as it would combine in the same sequential parent context
Either is prob ok then but I would prob use coll-of
With a :min-count constraint
I’m a bit torn about the fspec
thing though, I think it would be much more pleasant to see (s/fspec :args (s/cat) :ret (partial instance? MyRecord)
in a doc-string instead of ifn?
, but I can’t due to generative testing
I’m still new to spec so I’m kinda feeling it out, it’s very easy to overdo it and use it as a type system
Note that you can still run clojure.spec.test.alpha/check
on your function with the full fspec
-- independent of what the function's actual fdef
says. (right @alexmiller)
Or you could instrument
it with a different fspec
too I believe?
I'd probably fdef
it with a spec that is safe to instrument
, and then check
it with a more detailed fspec
...
(because it might, potentially, get instrumented by code far, far away in your code base that might "forget" to override the spec for it)