Skip to content

Commit db82e57

Browse files
committed
Reword f5fc090
- Titles are title-cased - Preserve continuity by emphasizing the features right after previous mentions. - Preserve continuity by using the same examples on this page. - Also demonstrate binding name shared with different patterns in the fall-through example. - Avoid using overly generic examples like `A`, `B`, `1` and `2`. Though here the immediacy from the specific examples isn't increased _that_ much. But still, helps remembering. - Avoid introducing one-off terms. Unfortunately more verbose than the previous version, but it might be needed.
1 parent f5fc090 commit db82e57

File tree

1 file changed

+75
-38
lines changed

1 file changed

+75
-38
lines changed

pages/docs/manual/latest/pattern-matching-destructuring.mdx

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ if (person1.TAG) {
299299

300300
**Note** how we've:
301301
- drilled deep down into the value concisely
302-
- using a nested pattern check `"Mary" | "Joe"` and `Vacations | Sabbatical`
302+
- using a **nested pattern check** `"Mary" | "Joe"` and `Vacations | Sabbatical`
303303
- while extracting the `daysLeft` number from the latter case
304304
- and assigned the greeting to the binding `message`.
305305

@@ -330,6 +330,39 @@ isBig \ myAnimal | Dog | Cat | Bird
330330
true | 1 | 2 | 3
331331
false | 4 | 4 | 5
332332

333+
### Fall-Through Patterns
334+
335+
The nested pattern check, demonstrated in the earlier `person` example, also works at the top level of a `switch`:
336+
337+
<CodeTab labels={["ReScript", "JS Output"]}>
338+
339+
```res prelude
340+
let myStatus = Vacations(10)
341+
342+
switch myStatus {
343+
| Vacations(days)
344+
| Sabbatical(days) => Js.log(`Come back in ${Js.Int.toString(days)} days!`)
345+
| Sick
346+
| Present => Js.log("Hey! How are you?")
347+
}
348+
```
349+
```js
350+
var myStatus = {
351+
TAG: /* Vacations */0,
352+
_0: 10
353+
};
354+
355+
if (typeof myStatus === "number") {
356+
console.log("Hey! How are you?");
357+
} else {
358+
console.log("Come back in " + (10).toString() + " days!");
359+
}
360+
```
361+
362+
</CodeTab>
363+
364+
Having multiple cases fall into the same handling can clean up certain types of logic.
365+
333366
### Ignore Part of a Value
334367

335368
If you have a value like `Teacher(payload)` where you just want to pattern match on the `Teacher` part and ignore the `payload` completely, you can use the `_` wildcard like this:
@@ -352,7 +385,47 @@ if (person1.TAG) {
352385

353386
</CodeTab>
354387

355-
`_` also works at the top level of the pattern like `| _ => ...` if you want to execute catch-all condition.
388+
`_` also works at the top level of the `switch`, serving as a catch-all condition:
389+
390+
<CodeTab labels={["ReScript", "JS Output"]}>
391+
392+
```res example
393+
switch myStatus {
394+
| Vacations(_) => Js.log("Have fun!")
395+
| _ => Js.log("Ok.")
396+
}
397+
```
398+
```js
399+
if (typeof myStatus === "number" || myStatus.TAG) {
400+
console.log("Ok.");
401+
} else {
402+
console.log("Have fun!");
403+
}
404+
```
405+
406+
</CodeTab>
407+
408+
**Do not** abuse a top-level catch-all condition. Instead, prefer writing out all the cases:
409+
410+
<CodeTab labels={["ReScript", "JS Output"]}>
411+
412+
```res example
413+
switch myStatus {
414+
| Vacations(_) => Js.log("Have fun!")
415+
| Sabbatical(_) | Sick | Present => Js.log("Ok.")
416+
}
417+
```
418+
```js
419+
if (typeof myStatus === "number" || myStatus.TAG) {
420+
console.log("Ok.");
421+
} else {
422+
console.log("Have fun!");
423+
}
424+
```
425+
426+
</CodeTab>
427+
428+
Slightly more verbose, but a one-time writing effort. This helps when you add a new variant case e.g. `Quarantined` to the `status` type and need to update the places that pattern match on it. A top-level wildcard here would have accidentally and silently continued working, potentially causing bugs.
356429

357430
### When Clause
358431

@@ -572,42 +645,6 @@ if (myNullableValue !== undefined) {
572645

573646
If you don't handle the `None` case, the compiler warns. No more `undefined` bugs in your code!
574647

575-
### Match multiple cases to one expression
576-
577-
Now, sometimes you may want to pattern-match on large but finite sets of possibilities where many possibilities map to the same expression. In these cases, wildcards can seem tempting because they reduce code duplication, but there's another option, often termed disjunctive patterns, that allow you to map multiple patterns to a single expression. That is, you can replace:
578-
579-
```res example
580-
type t = A | B | C | D | E
581-
let v = C
582-
switch v {
583-
| A => 1
584-
| _ => 2
585-
}
586-
```
587-
588-
with:
589-
590-
```res example
591-
type t = A | B | C | D | E
592-
let v = C
593-
switch v {
594-
| A => 1
595-
| B | C | D | E => 2
596-
}
597-
```
598-
599-
This still requires a bit more work than a wildcard, but it has the advantage of ensuring the compiler can enforce exhaustiveness, unlike a wildcard based solution. Additionally, unlike wildcards, you can easily refactor your code to have multiple pattern sets, like so:
600-
601-
```res example
602-
type t = A | B | C | D | E
603-
let v = C
604-
switch v {
605-
| A => 1
606-
| B | C => 2
607-
| D | E => 3
608-
}
609-
```
610-
611648
## Conclusion & Tips & Tricks
612649

613650
Hopefully you can see how pattern matching is a game changer for writing correct code, through the concise destructuring syntax, the proper conditions handling of `switch`, and the static exhaustiveness check.

0 commit comments

Comments
 (0)