Pattern Matching
Matching on Enums
Flix supports pattern matching on algebraic data types.
For example, if we have an algebraic data type that models shapes:
enum Shape {
case Circle(Int32)
case Square(Int32)
case Rectangle(Int32, Int32)
}
Then we can write a function to compute the area of a Shape
using pattern
matching:
def area(s: Shape): Int32 = match s {
case Shape.Circle(r) => 3 * (r * r)
case Shape.Square(w) => w * w
case Shape.Rectangle(h, w) => h * w
}
Let Pattern Match
In addition to the pattern match
construct, a let-binding can be used to
destruct a value. For example:
let (x, y, z) = (1, 2, 3)
Binds the variables x
, y
, and z
to the values 1
, 2
, and 3
,
respectively.
Any exhaustive pattern may be used in a let-binding. For example:
let (x, Foo(y, z)) = (1, Foo(2, 3))
is legal provided that the Foo
constructor belongs to a type where it is the
only constructor.
The following let-bindings are illegal because they are not exhaustive:
let (1, 2, z) = ...
let Some(x) = ...
The Flix compiler will reject such non-exhaustive patterns.
Match Lambdas
Pattern matches can also be used with lambda expressions. For example:
List.map(match (x, y) -> x + y, (1, 1) :: (2, 2) :: Nil)
is equivalent to:
List.map(w -> match w { case (x, y) => x + y }, (1, 1) :: (2, 2) :: Nil)
As for let-bindings, such pattern matches must be exhaustive.
Note the difference between the two lambda expressions:
let f = (x, y, z) -> x + y + z + 42i32
let g = match (x, y, z) -> x + y + z + 42i32
Here f
is a function that expects three Int32
arguments, whereas g
is a
function that expects one three tuple (Int32, Int32, Int32)
argument.