This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-04-15
Channels
- # announcements (2)
- # babashka (41)
- # beginners (10)
- # calva (62)
- # chlorine-clover (70)
- # cider (19)
- # clara (2)
- # clj-http (1)
- # clj-kondo (1)
- # cljs-dev (3)
- # cljsrn (8)
- # clojure (168)
- # clojure-austin (1)
- # clojure-australia (2)
- # clojure-canada (1)
- # clojure-europe (15)
- # clojure-france (9)
- # clojure-nl (3)
- # clojure-serbia (5)
- # clojure-spec (14)
- # clojure-uk (8)
- # clojurescript (14)
- # community-development (30)
- # core-async (42)
- # core-typed (1)
- # datahike (2)
- # datalog (23)
- # datomic (4)
- # emacs (4)
- # figwheel-main (4)
- # fulcro (67)
- # ghostwheel (4)
- # girouette (1)
- # gorilla (7)
- # graalvm (11)
- # heroku (8)
- # integrant (42)
- # jobs (6)
- # jobs-discuss (47)
- # kaocha (7)
- # lambdaisland (2)
- # leiningen (5)
- # lsp (29)
- # off-topic (1)
- # pathom (9)
- # portal (6)
- # re-frame (5)
- # reagent (11)
- # releases (6)
- # remote-jobs (10)
- # shadow-cljs (112)
- # testing (55)
- # vrac (1)
I could use some guidance on using clojure.spec to validate input arguments to a function. Here’s some context:
• I am debating instrumenting with fdef
vs. using :pre
and :post
conditions.
• The function is internal to the app and the argument values are completely under the control of the programmer (i.e. there is no validation of external data going on).
I was initially leaning toward instrumenting with fdef
because I see this as a check for program correctness rather input validation. It should be safe to turn this check off in production with no change in behavior.
But I want the instrumentation to be turned on by default during development and turned off by default in production. I can imagine ways to achieve that, but the fact that I couldn’t find any mention of a typical pattern for doing that (e.g. my understanding is that assert
is set up to be easily enabled/disabled in a blanket manner) made me think I might be missing something.
Another thing I should mention is that I have no intention of ever testing this function with generative tests. It’s not a good fit for generative testing.
> I was initially leaning toward instrumenting with fdef because I see this as a check for program correctness rather input validation.
what's this
?
(I can interpret it in two different ways)
Yeah, that’s fair. this = “this solution I’m designing”, not this = “instrumenting with fdef”.
If ease of turning on/off is the main concern, perhaps I'd go for fdef because it's the default choice, and toggling it globally, and both for inputs and outputs seems relatively easy with https://github.com/jeaye/orchestra
There are reasons beyond toggling ease why some people might prefer assert
to instrumentation. https://github.com/fulcrologic/guardrails or https://github.com/nedap/speced.def (disclaimer: I authored it) and probably a couple more libraries favor it.
There's no fixed truth in the topic, but in absence of other concerns I'd probably 'start small'.
@U45T93RA6 Thanks a ton! I need to digest this more and check out orchestra. Off the top of my head, my only concern is that I usually like to be a little wary about adding new dependencies if I don’t have to.
Are you talking about clojure.core/assert or s/assert? Seems like the latter would be good here
Thanks! Somehow I missed s/assert
, I think you’re right. Maybe s/assert
in a :pre
condition…
I'd put it in the mainline
s/assert in mainline code is designed so that it can be compiled completely out of the program via https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html#clojure.spec.alpha/*compile-asserts*
Hello. Where i have several defined and registered predicates, can i compose them in this state?
;; contrived example
(s/def ::string-starts-with-an-a? (s/and string? #(string/starts-with? % "a")))
(s/def ::not-an-apple? #(not= "apple" %))
(s/def ::starts-with-an-a-but-not-an-apple? (s/and ::string-starts-with-an-a? ::not-an-apple?))
predicate composing after registration
disregard the above. my forms had not been evaluated, thus the error received was entirely my doing