I like the idea of generating bindings from capture groups. However, how should it work with the pin operator?
const regex = /(?<left>\d+) \+ (?<right>\d+)/;
match (res) {
when (^regex) { process(left, right); }
}
If the pin operator works and the res is then compared with the evaluated regex, then left and right is not statically analyzable.
If the pin operator does not work (maybe a runtime error when regex is not a primitive value?), this feature becomes a refactoring hazard because the regex in the WhenClause can not be reused.
We could require that for regex one must manually offers the capture groups:
const regex = /(?<left>\d+) \+ (?<right>\d+)/;
match (res) {
when (^regex as { groups: { left, right } } ) { process(left, right); }
}
Related: #189
We need to refactor the README, but if you go to the code samples section and scroll to the example beginning with match (arithmeticStr), you'll see the following:
Additionally, it would be nice for regex literals to be able to introduce bindings without the with keyword. This would be a magic special case, but we find it acceptable since it’s still possible to statically analyze the source of all bindings.
Regexes stored behind a variable will have to be used like so:
match (res) {
when (^regex) with { groups: { left, right }} { process(left, right); }
}
Could you elaborate on the refactoring hazard you refer to, if it's still relevant? I'm not sure I understand - perhaps an example would be helpful.
In other words, expression regexes (with the pin operator) must always explicitly specify bindings if they want them available, just like any other expression that participates in the matching protocol.
For regex patterns, the two options are:
(Clarifying some terminology: here, a "regex pattern" exclusively means regex _literals_. So /^foobar$/ is a "regex pattern", but ^SOME_REGEX_IN_A_VARIABLE is an "expression regex". Terminology is still a bit loose for us at this stage! 😆)
I assume that with and as in your code examples are semantically equivalent and it is only a choice of styles.
Alright it seems not as I am reading https://github.com/tc39/proposal-pattern-matching/issues/188#issuecomment-837783929.
When people refactor
match (res) {
when (/(?<left>\d+) \+ (?<right>\d+)/) { process(left, right); }
}
to
const regex = /(?<left>\d+) \+ (?<right>\d+)/;
match (res) {
when (^regex) { process(left, right); }
}
they will see an early error because left is undefined. And _if_ we don't support
match (res) {
when (^regex) with { groups: { left, right }} { process(left, right); }
}
the regex will be locked to the match expression, which keeps people from refactoring the regex here. But since we do support it, I am good with current solution.
Context: I am designing ESTree AST for this proposal. Since the spec is out-of-dated, I read through examples. And when the example does not mention certain cases I will open a feedback to confirm if it should work or fail.
@JLHwung they are not equivalent; with is a chained matching clause that can also produce bindings, and as is only producing bindings without doing any matching. There's ongoing discussion about simplifying things here.
You are correct that the second example will be an early error. The third example is explicitly already supported, for the reasons you state.
Closing as it works as expected. Thanks for clarifying!
Most helpful comment
We need to refactor the README, but if you go to the code samples section and scroll to the example beginning with
match (arithmeticStr), you'll see the following:Regexes stored behind a variable will have to be used like so:
Could you elaborate on the refactoring hazard you refer to, if it's still relevant? I'm not sure I understand - perhaps an example would be helpful.