Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

speced/get-in #48

Open
vemv opened this issue Apr 17, 2019 · 4 comments
Open

speced/get-in #48

vemv opened this issue Apr 17, 2019 · 4 comments

Comments

@vemv
Copy link
Contributor

vemv commented Apr 17, 2019

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

@thumbnail
Copy link
Member

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.

@vemv
Copy link
Contributor Author

vemv commented Aug 29, 2019

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.

@thumbnail
Copy link
Member

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 🤔

@vemv
Copy link
Contributor Author

vemv commented Sep 1, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants