First of all, looks like an interesting proposal!
I think it would be useful to be able to use pattern matching with existing control structures too.
I use the infix keyword "matches" in the following examples, however other options could be considered.
For example:
if (res instanceof Response && res matches { status: 200, content }) {
return content;
}
// do something else
const arr = [];
while (iterable.next() matches { done: false, value }) {
arr.push(value);
}
You certainly can do this, since the match construct is an expression:
if (match (res) { when ({ status: 200, content }) if (res instanceof Response) { true } else { false } }) {
return content;
}
I don't think it'd be worth adding _another_ syntax form just so it reads more sentence-like :-)
Does that meet your needs?
There is actually prior art for this: https://doc.rust-lang.org/std/macro.matches.html
if res.is_response() && matches!(res, Response { status: 200 }) {
}
I think this may be worth considering.
Here's your second example, using the stage 2 iterator helpers proposal, if it ends up including takeWhile:
const arr = iterable.takeWhile(x => match (x) { when(^value) { true } else { false } }).toArray();
You certainly can do this, since the match construct is an expression:
if (match (res) { when ({ status: 200, content }) if (res instanceof Response) { true } else { false } }) { return content; }I don't think it'd be worth adding _another_ syntax form just so it reads more sentence-like :-)
Does that meet your needs?
Thanks for the quick reply!
Not to discredit your impressive work, but this doesn't seem very readable to me 馃槃 ?
I didn't see this described in the README, although perhaps I missed this? If not, might be a good idea to document with a few examples?
@mpenney99 Since the matches!() is a macro in Rust, maybe it could be later replicated via babel-macro?
I agree it's not very readable - I'd personally not put matching logic inline anywhere like that, i'd store the result in an intermediate variable. I'm not sure examples with poor readability are useful in the readme :-)
Here's one way i'd personally write it:
const matched = match (res) {
if (res instanceof Response) when ({ status: 200, content }) {
true;
}
else {
false;
}
});
if (matched) {
return content;
}
Okay, I had another look at this. In your first example, you wouldn't be able to expose "content" to the scope of the if-block, right? It would only be available within the scope of the match() expression?
Anyway, I think the fundamental problem here is that match() is designed as a replacement for the switch block. I definitely agree it's worth-while to address some of the existing limitations and foot-guns here (accidental fall-through, assigning the result to a variable). And there's a lot of prior-art here too (even Java has switch expressions now!).
However, for me it still feels like pattern-matching is kind of a separate concern (but could be you disagree!). I think it would be good to consider how pattern-matching could be used alongside existing structures and also with imperative code.
@mpenney99 aahhhh yes, that's true. in that case:
match (res) {
if (res instanceof Response) when ({ status: 200, content }) { return content; }
else {}
};
should do it?
I notice the pattern match (x) { when(^value) { true } else { false }. It looks like if (sth) return true; else return false; to me
Rather than extending other statement grammars, it would be rather nice to have an instanceof-like operator that allowed you to compare any expression against a pattern.
Just to keep it separate from the current proposal syntax to avoid any confusion, I'm going to us a is operator:
<expression> is (<pattern>)
if (res is ({ status: 200 })) {
// ...
}
I don't believe there's any existing mechanism like this, but ideally this syntax would also allow you to create bindings in the "current" scope (block-scoped, similar to how for (let ...) works today):
if (res is ({ status: 200, body })) {
console.log(body)
}
There is also prior art for this sort of behavior in Rust:
if let Some(value) = res {
println!("{}", value)
}
// same as:
match res {
Some(value) => {
println!("{}", value)
}
}
The particular syntax of this pattern matching proposal does get a bit weird looking with an if clause:
if (res is ({ status }) if (status >= 400)) {
// ...
}
I'd argue that's acceptable weirdness though.
@jamiebuilds that's captured by #191 :-)
Most helpful comment
@jamiebuilds that's captured by #191 :-)