Fork me on GitHub
#clojure-uk
<
2022-05-30
>
folcon22:05:47

I've been reminding myself how to use spec and one thing I can't remember is how to get better errors from this sort of thing?

(defn load-order [order-book {:keys [side id] :as order}]
  {:pre [(s/valid? :order/order order)]}
  (assoc-in order-book [side id] order))
Which does give me this:
Execution error (AssertionError) at fruit-economy.sim.market/load-order (market.clj:23).
Assert failed: (is (s/valid? :order/order order))
But considering it's a spec, I was expecting a little more? I've hacked it a bit by wrapping it in an is, which gives me:
FAIL in () (market.clj:2)
expected: (s/valid? :order/order order)
  actual: (not
           (s/valid?
            :order/order
            {:price 1,
             :size 425.0,
             :side :sell,
             :id 10229,
             :good-kw :inventory}))
But I'm sure there's a better way?

jcf05:05:23

Unfortunately, :pre doesn’t really understand specs so can only assert that a non-truthy value occurred. Three options spring to mind… You could use s/assert outside of your precondition, and enable checking. If you use fdef to specify your :args and turn on instrumentation, you’ll get an error with an explanation. https://clojuredocs.org/clojure.spec.alpha/fdef Alternatively, test your specified function and don't call it with the wrong input. Validate data at the boundary (this one might be a little idealistic).

jcf08:05:01

It might be worth asking over in #clojure-spec too?

folcon11:05:08

Thanks 😃