Skip to content

Commit 5c43fbd

Browse files
committed
[patterns] Allow extractor patterns to match enum values too.
1 parent 28f278c commit 5c43fbd

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

working/0546-patterns/patterns-feature-specification.md

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -874,13 +874,7 @@ switch (obj) {
874874
An extractor combines a type test and record destructuring. It matches if the
875875
object has the named type. If so, it then uses the following record pattern to
876876
destructure fields on the value as that type. This pattern is particularly
877-
useful for writing code in an algebraic datatype style.
878-
879-
```
880-
extractMatcher ::= typeName typeArgumentsOrBinders? "(" recordFieldMatchers ")"
881-
```
882-
883-
For example:
877+
useful for writing code in an algebraic datatype style. For example:
884878

885879
```dart
886880
class Rect {
@@ -898,12 +892,43 @@ display(Object obj) {
898892
}
899893
```
900894

895+
You can also use an extractor to both match an enum value and destructure
896+
fields from it:
897+
898+
```dart
899+
enum Severity {
900+
error(1, "Error"),
901+
warning(2, "Warning");
902+
903+
Severity(this.level, this.prefix);
904+
905+
final int level;
906+
final String prefix;
907+
}
908+
909+
log(Severity severity, String message) {
910+
switch (severity) {
911+
case Severity.error(_, prefix):
912+
print('!! $prefix !! $message'.toUppercase());
913+
case Severity.warning(_, prefix):
914+
print('$prefix: $message');
915+
}
916+
}
917+
```
918+
919+
The grammar is:
920+
921+
```
922+
extractMatcher ::= extractName typeArgumentsOrBinders? "(" recordFieldMatchers ")"
923+
extractName ::= typeIdentifier | qualifiedName
924+
```
925+
901926
It requires the type to be a named type. If you want to use an extractor with a
902927
function type, you can use a typedef.
903928

904-
It is a compile-time error if `typeName` does not refer to a type. It is a
905-
compile-time error if a type argument list is present and does not match the
906-
arity of the type of `typeName`.
929+
It is a compile-time error if `extractName` does not refer to a type or enum
930+
value. It is a compile-time error if a type argument list is present and does
931+
not match the arity of the type of `extractName`.
907932

908933
**TODO: Some kind of terse null-check pattern that matches a non-null value?**
909934

@@ -1540,12 +1565,14 @@ To match a pattern `p` against a value `v`:
15401565
1. If `v` is not a subtype of the extractor pattern's type, then the
15411566
match fails.
15421567

1543-
2. Otherwise, match `v` against the subpatterns of `p` as if it were a
1568+
2. If the extractor pattern refers to an enum value and `v` is not that
1569+
value, then the match fails.
1570+
1571+
3. Otherwise, match `v` against the subpatterns of `p` as if it were a
15441572
record pattern.
15451573

1546-
**TODO: Define order of evaluation and specify how much freedom compilers have
1547-
to reorder or skip tests. What happens if the various desugared operations have
1548-
side effects?**
1574+
**TODO: Update to specify that the result of operations can be cached across
1575+
cases. See: https://github.com/dart-lang/language/issues/2107**
15491576

15501577
### Late and static variables in pattern declaration
15511578

@@ -1582,6 +1609,8 @@ main() {
15821609

15831610
- Add if-case statement.
15841611

1612+
- Allow extractor patterns to match enum values.
1613+
15851614
### 1.1
15861615

15871616
- Copy editing and clean up.

0 commit comments

Comments
 (0)