-
Notifications
You must be signed in to change notification settings - Fork 81
feat(patterns): Add M.choose
#3073
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
base: gibson-3046-narrow-rankcover
Are you sure you want to change the base?
feat(patterns): Add M.choose
#3073
Conversation
|
M.discriminated
| const { [keyName]: _, ...rest } = specimen; | ||
| const subPatt = patts[keyValue]; | ||
| return confirmNestedMatches(freeze(rest), subPatt, label, reject); |
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.
rest is constructed by destructuring. The Jessie Must freeze API Surface Before Use don't seem to capture this case.
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.
The specimen must already be passable and therefore hardened. Given that, only the top level of rest is not frozen. Everything deeper is frozen. Therefore, the freeze here means the code does uphold the purpose "Must freeze API Surface Before Use". The lack is on the Jessie side, where we don't have any syntactic machinery to recognize that this code conforms.
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.
yes, this code conforms.
My comment aims to say: the Jessie rules don't seem to say that you need a harden(...) here.
dckc
left a comment
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.
the feature looks nice,
but the upgrade/compatibility considerations make my head hurt
erights
left a comment
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.
discriminatedmore accurately communicates these constraints thanchoose, and if we ever want to relax them, that would be the time for a more generic name.
I technically agree with the premise but disagree on the conclusion. "discriminated" imposes more pain from its verbosity than it saves from its slightly more precise meaning.
I like "choose". But if we want something else, please something short. Once this exists, if the name is short, it may be used a lot.
The original "choose" suggestion was never implemented, so there's no conflict using "choose".
@dckc please expand? I don't see it. |
|
Brevity is the soul etc. I would go with |
2243aaf to
f44f256
Compare
Right, but I believe the original suggestion was also more powerful than what is being added here (and at any rate, more powerful approaches that iterate an array in some way rather than indexing into a record are certainly possible). @erights @kriskowal are we comfortable with burning the "match:choose" tag on this narrow functionality? Note that future updates to And regardless, note that this PR currently builds upon #3053, which still needs approval. |
5fd2b94 to
4a911fc
Compare
Co-authored-by: Mark S. Miller <[email protected]>
0a773b1 to
251a6c3
Compare
251a6c3 to
4095f10
Compare
I am. If we ever add the more general one, it will be used far less that this one and so can have a more awkward name. And, I doubt we will ever add the more general one. |
|
Done. |
|
If you're happy with this PR, please also approve its #3053 foundation so I can merge that one first. |
maybe just PTSD from the endo interfaces backwards-incompatible change... combined with recent experience where adding a field seemed innocent, until a consumer grabbed the new pattern before a producer got upgraded, and BLAMMO. I don't have a theory for how the vocabulary of pattern matchers evolves through ALL layers of our system. |
|
For reference, Zod calls this |
M.discriminatedM.choose
Fixes #3072
Extends #3053 for avoiding known fast-check failures
Description
Add support for
M.choose(keyName, { keyValue1: restPatt, keyValue2: restPatt, … }). This differs from theM.choose(keyName, [{ [keyName]: keyValue1, … }, { [keyName]: keyValue2, … }, …])suggestion of #3072 in a handful of ways:{ keyValueN: M.recordOf(M.string(), M.any() }is just fine.feat(patterns): Adddiscriminatedmore accurately communicates these constraints thanchoose, and if we ever want to relax them, that would be the time for a more generic name.M.choose#3073 (comment)For reference, Zod calls this
discriminatedUnionand its API is similar to the original suggestion—defined from a string key name and an array of disjoint object patterns, each of which must define the corresponding key with a value that is either a literal or a string enumeration and does not match any value that would also be matched by another pattern in the array, which I think means it's actually slightly weaker than what we have here (because our sub-patterns are not limited to object matchers and can be e.g.M.or(…)/M.splitRecord(…)/etc. for covering non-trivial combinations of fields).Security Considerations
None known.
Scaling Considerations
As mentioned above, this is faster than
M.orbecause it never considers more than one sub-pattern.Documentation Considerations
Hopefully covered by JSDoc.
Testing Considerations
Covered by new unit tests.
Compatibility Considerations
I don't think matchers can ever expand beyond their initial shape, so if this is accepted then it will always have its current limitations (specifically,
match:choosematchers cannot grow support for non-static key matching because matchers theirselves are passable and the shape introduced here has no way to express it—but future changes could still updateM.choose(…)to return instances of a new type).Upgrade Considerations
Changes are purely additive, so I think the only possible upgrade issue would be if new code passes a
match:chooseinstance to old code that tries to match against it. I'm not aware of any such old code that cannot itself be upgraded.