speced.def
speced.def copied to clipboard
speced/get-in
(speced/get-in {:foo 2} [:foo :bar :baz]) => error message explaining that 2 does not contain :bar
(speced/get-in {:foo {:bar {}}} [:foo :bar :baz] ::default) => ::default
(speced/get-in {:foo 2} [:foo :bar :baz] ::default) => error message explaining that 2 does not contain :bar
The latter behavior is interesting. Fallback values should only be offered if the last member of the chain was missing, but not for intermediate values.
Essentially it ensures the structure is as expressed.
Interesting feature!
Fallback values should only be offered if the last member of the chain was missing, but not for intermediate values.
I don't agree, it also deviates from core/get-in behavior. if the desired shape is required there's other ways of ensuring that.
Thanks for the feedback!
it also deviates from core/get-in behavior
quite obviously I'm aware of this.
A core idea of speced.def (or clojure.spec in general?) is that a given app has a specific schema and that it should be honored, with fail-fast behavior when that premise is broken.
clojure.core/get-in (and update-in, etc) go in the opposite direction: they give you a free ticket to act liberally towards your data.
let's say that after a schema change, [:some :path 42] should have been refactored to [:some :42], but it wasn't, due to human mistake.
Now something fails, possibly in another ns, or even a different project. How do you debug it? Fail-fast behavior points right at the culprit instead of making you go in a bug hunt from defn to defn / from ns to ns.
Now something fails, possibly in another ns, or even a different project. How do you debug it? Fail-fast behavior points right at the culprit instead of making you go in a bug hunt from defn to defn / from ns to ns.
I see, but aren't speced/(let|defn|def) more appropriate to make sure such a contract are held?
destructuring in speced/* doesn't raise errors unless you add a spec.
I was thinking about allowing the consumer to specify specs on keys in the get-in vector; but metadata can't be applied to to keywords/numbers so that wouldn't work 🤔
I see, but aren't speced/(let|defn|def) more appropriate to make sure such a contract are held?
They are not more appropiate for the precise stated reason: their error reports can happen arbitrarily later (and farther away) than the actual source of the error.
To put it in another POV: when you refactor shapes in a codebase, you often have to refactor get-ins as well. This tool would make that refactoring much safer / less tedious to perform.
destructuring in speced/* doesn't raise errors unless you add a spec.
Not sure of how destructuring is related to the topic