-
Notifications
You must be signed in to change notification settings - Fork 213
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
Polymorphic schemas #1053
Polymorphic schemas #1053
Conversation
docs/function-schemas.md
Outdated
[:=> [:cat [:enum 50]] [:enum 50]] | ||
[:=> [:cat [:enum 5333344553]] [:enum 5333344553]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you have three different schemas here? I know the two enums are technically different, but maybe :nil
, [:enum 50]
and [:map-of :keyword :any]
or something would better clarify what's happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently it really is this simple, more like:
[:fn {:gen/return nil} (fn [r] (= nil r))]
[:fn {:gen/return 50} (fn [r] (= 50 r))]
[:fn {:gen/return 5333344553} (fn [r] (= 5333344553 r))]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh interesting, okay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To go further we'll need to think about what it means to shrink a schema. There are ideas in the spec impl of this, but this is the minimal proof-of-concept.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will elaborate on exactly what happens in the docs though, thanks for the feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found the reason I needed such a convoluted representation in the first place: #1070
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will elaborate on exactly what happens in the docs though, thanks for the feedback.
Done.
Moved to frenchy64#11 |
Close #846
Depends on #1071
I went through several iterations on the internal representation. It felt correct once the serialized
form
of a polymorphic schema was human readable and ergonomic (doesn't require quoting to evaluate correctly, so no symbols allowed). The tradeoff is that we need to implement capture-avoiding substitution, and that's very error-prone. I tested a few cases.The identity schema's
form
is[:all [:X] [:-> :X :X]]
. It's introduced with them/all
macro by(m/all [X] [:-> X X])
.To instantiate it, you perform a
walk/postwalk-replace
with{:X this-to-instantiate}
.The extra
:schema
's make sure regex's don't splice. By default, variables are single schemas.This representation is delicate, but works and is serializable if a few rules are followed:
It's a leaf schema, and it's essential that its body is not manipulated by users before instantiating it.
For example, variables are renamed if they clash with any keywords in the body:
m/inst
also does renaming to avoid capture. A variable can be "captured" by any schema, not just another variable, since variables are keywords and so are schemas.The following renames to
:y0
because if it was:y
, then instantiation would destroy the body via(postwalk-replace {:y ...})
.I don't know how to generate polymorphic functions, but there's some ideas in my deterministic function PR #1042
The
mg/check
implementation is pretty simple and can be improved. It just instantiates variables to very small schemas of a single value.