Last active
January 20, 2017 17:12
-
-
Save dabbott/f39458157e7d50a3428deb1a183ad247 to your computer and use it in GitHub Desktop.
JavaScript Match Expression
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Match expression | |
// | |
// `match` behaves similarly to `switch`. `match` is an expression, while `switch` is | |
// a statement, but the main idea is the same. The value of the `match` expression is | |
// the completion value of the chosen case. | |
// | |
// Since we might not be able to use the name `match` due to how common it is in | |
// existing code (e.g. String.prototype.match), alternative ideas: | |
// | |
// switch* pattern match* | |
// | |
// However, you can use `async` as a variable name despite it being a keyword, so | |
// maybe this isn't a big deal, so long as the grammar isn't ambiguous. | |
// | |
// ----- | |
// Example 1. Matching literals | |
// | |
// Here `match` can be seen as a convenient replacement for switch, when a completion | |
// value is needed. | |
const str = 'yes' | |
const simple = match (str) { | |
case 'yes': true | |
case 'no': false | |
default: null | |
} | |
console.log(simple) // => true | |
// Example 2. Destructured array matching | |
// | |
// The real power of match comes when we start destructuring arrays and objects. | |
// Here we merge two sorted arrays by destructuring the arrays. | |
const merge = (xs, ys) => | |
match (xs, ys) { | |
case ([], ys): ys | |
case (xs, []): xs | |
case ([x, ...xs], [y, ...ys]): | |
if (x < y) [x, ...merge(xs, [y, ...ys])] | |
else [y, ...merge([x, ...xs], ys)] | |
} | |
console.log(merge([2], [1, 3])) // => [1, 2, 3] | |
// Example 3. Destructured object matching | |
// | |
// Here we check an object for several different cases. Note that we can check for | |
// the existence of a key, or for a specific value of a key. The syntax is the same | |
// as the left-hand-side of destructured assignment. | |
const obj = { first: 'Devin', last: 'Abbott', awesome: true } | |
const fullname = match (obj) { | |
case { first, last }: `${first} ${last}` | |
case { first }: `${first}` | |
case { awesome = true }: `No name needed, too awesome` | |
default: `Invalid name: 'first' field required` | |
} | |
console.log(fullname) // => "Devin Abbott" | |
// Other ideas | |
// match could be a function expression, e.g. | |
// const f = match (x, y) => { case (1, 2): 'ok' } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment