Skip to content

Commit 466da83

Browse files
Add reference doc
1 parent e5a73b0 commit 466da83

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
layout: doc-page
3+
title: "Match Expressions with Sub Cases"
4+
---
5+
6+
A case in a match expression can be followed by another sub-match expression, introduced by the `if` keyword.
7+
For example:
8+
9+
```scala
10+
enum Version:
11+
case Legacy
12+
case Stable(major: Int, minor: Int)
13+
14+
case class Document(title: String, version: Version)
15+
16+
def version(d: Option[Document]) = d match
17+
case Some(x) if x.version match
18+
case Version.Stable(m, n) if m > 2 => s"$m.$n"
19+
case Version.Legacy => "legacy"
20+
case _ => "unsupported"
21+
22+
assert(version(Some(Document("...", Version.Stable(3, 1)))) = "3.1")
23+
assert(version(Some(Document("...", Version.Stable(2, 1)))) = "unsupported")
24+
assert(version(Some(Document("...", Version.Legacy))) = "legacy")
25+
assert(version(Some(Document("...", None))) = "unsupported")
26+
```
27+
28+
The cases of a sub-match expression are tested iff the outer case matches.
29+
The sub match scrutinee can refer to variables bound from the outer pattern.
30+
Evaluation of sub-matches then proceeds as usual.
31+
For example, if `version` is applied on `Some(Document("...", Version.Stable(3, 1)))`, the first outer pattern matches (i.e., `Some(x)`), causing the sub match expression to be evaluated with scrutinee `Version.Stable(3, 1)`, yielding `"3.1"`.
32+
33+
The cases of a sub-match expression need not be exhaustive.
34+
If they were, we would not need sub-match at all: a usual match in the body of the first case would suffice,
35+
e.g., `case Some(x) => x.version match ...`.
36+
If none of the sub-cases succeed, then control flow returns to the outer match expression and proceeds as though the current case had not matched.
37+
For example, `Some(Document("...", Version.Stable(2, 1)))` matches the first pattern, but none of its sub-cases, and we therefore obtain the result `"unsupported"`.
38+
39+
More generally, sub-matches also allow:
40+
- Arbitrary nesting, e.g. sub-sub-matches are supported.
41+
- Interleaved boolean guards, e.g. `case Some(x: Int) if x != 0 if x match ...`.
42+
- Interleaving pattern extractors and computations for the scrutinees of sub-matches.
43+
44+
45+
## Motivation
46+
47+
Without sub matches, one would typically duplicate either the default case or the outer pattern.
48+
That is, use:
49+
```scala
50+
def version(d: Option[Document]) = d match
51+
case Some(x) => x.version match
52+
case Version.Stable(m, n) if m > 2 => s"$m.$n"
53+
case Version.Legacy => "legacy"
54+
case _ => "unsupported"
55+
case _ => "unsupported"
56+
```
57+
or
58+
```scala
59+
def version(d: Option[Document]) = d match
60+
case Some(Document(_, Version.Stable(m, n))) if m > 2 => s"$m.$n"
61+
case Some(Document(_, Version.Legacy)) => "legacy"
62+
case _ => "unsupported"
63+
```
64+
65+
66+
67+
68+
69+
70+
71+
72+

0 commit comments

Comments
 (0)