Patterns
Patterns are used to bind values to variables, and as 'conditions' in
match
-expressions. Patterns match a set of values,
and bind (essentially assigns) a set of partial values to variables.
Name patterns
The simplest pattern is a
variable name, like x
. It matches all values, and binds the value to the
name, x
in this case.
Literal patterns
Integers and booleans can be matched on literals of their type. For example,
true
only matches booleans that are true
and 10
only matches integers
whose value is 10
. Literal patterns do not bind any variables.
Tuple patterns
Another simple pattern is the tuple-pattern. It matches tuples of a specific length, and binds all elements of the tuples to sub-patterns. All patterns can be nested
For example
let ((a, b), c) = ((1, 2), 3);
will result in a=1
, b=2
and c=3
.
If parts of a tuple pattern are conditional, the pattern will only match if the subpatterns do. For example,
match (x, y) {
(true, _) => true,
_ => false,
}
will only return true if x
is true, and false otherwise
Struct and enum patterns
Named patterns are used to match structs and enum variants. They consist of the name of the type or variant, followed by an argument list if the type has arguments.
Argument lists can be positional: ()
or named: $()
. In a positional
argument list, the fields of the type are matched based on the order of the
fields. In a named list, patterns are instead bound by name, either
field_name: pattern
or just field_name
which binds a new local variable
field_name
to field. Argument matching in patterns works the same way as in
argument lists during instantiation
This is best shown by examples
struct S {
x: int<8>,
y: int<8>,
}
// Positional pattern, binds `a` to the value of `x` and `b` to the value of `y`
S(a, b)
// Named pattern with no shorthand. The whole pattern matches if the `y` field is `0`
// in which case `a` will be bound to the value of `x`
S$(y: 0, x: a)
// Shorthand named. This binds a local variable `y` to the value of the field `y`. The field `x` is ignored.
S$(y, x: _)
enum
variants work the same way, but only match the enum of the specified name. For example
enum E {
A,
B{val: int<8>}
}
match e {
E::A => {},
E::B(0) => {},
E::B(val) => {}
}
Wildcard
The wildcard pattern _
. It matches all values but does not bind the value to any
variable. It is useful as a catch-all in match blocks
For example, if we want to do something special for 0
and 1
, but don't care about other
values we might write:
match integer {
0 => {},
1 => {},
_ => {}
}