-
Notifications
You must be signed in to change notification settings - Fork 3
NEP8 Pattern Matching
This proposal introduces pattern matching to provide a shortcut way to deconstruct compound values.
Consider a fragment of code that needs to inspect an array, and extract the second element if the first element is 1. Without pattern matching, this might be written as follows:
VAR a: Array<Number>
% ... populate a
IF a.size() >= 2 AND a[0] == 1 THEN
LET x: Number := a[1]
% ... process x
END IF
This uses a compound condition to test the first element and requires a second LET
statement to extract x
.
With pattern matching, this could be written as:
VAR a: Array<Number>
% ... populate a
IF MATCH [1, x, ...] := a THEN
% ... process x
END IF
A pattern is a new grammatical construct that looks like a literal value, but with a different structure. The following things can be match targets:
- A constant value, to match that value exactly.
- An identifier, to capture a value and make the value available under the given name in the following scope.
- Another pattern value (to support nested patterns).
- An underscore, as a placeholder to match anything but ignore its value.
-
Arrays: Arrays perhaps provide the most flexibility in matching. Not only can any element be matched, but a subarray may be extracted as well using
...
notation. Examples:-
[x]
- match an array with exactly one element and extract the value intox
-
[x, a...]
- extract the first element intox
, and the remainder of the array (which may be empty) intoa
-
[x, ...]
- extract the first element intox
, but the array may contain more elements (which are not extracted) -
[..., z]
- extract the last element intoz
-
[x, y, a..., z]
- extract the first element intox
, the second intoy
, the last intox
, and the remainder between them intoa
There may not be more than one
...
in an array pattern. -
-
Dictionaries: Dictionaries can be matched on values of specific keys but there is no provision for extracting a subdictionary. Examples:
-
{"foo": x}
- match a dictionary with exactly one keyfoo
, and extract the value intox
-
{"foo": x, ...}
match a dictionary with any number of keys, one of them beingfoo
-
-
Records: Records can be pattern matched using their constructor syntax:
-
Rec(foo WITH x)
- match any record of typeRec
and extract the value of fieldfoo
intox
-
-
Interface pointers: Polymorphic classes can be matched against their actual type using the following syntax:
-
POINTER TO Cls(foo WITH x)
- match a pointer to an instance ofCls
, extract fieldfoo
asx
-