Pattern Matching
As filtrera is not proceedural, control-flow using classic if-statements doesn’t make much sense, and are not part of the language. Instead filtrera provides powerful pattern matching to cover any conditional control flow you might need.
Pattern matching is carried by two keywords:
is
functions as an operator and matches the left hand side with the right hand pattern. The
result is a boolean.
match
is more powerful and allows you to create separate paths given a path. But before we
get to that, let’s discuss what a pattern is.
A pattern is any type descriptor. Since types can be literal, a pattern can also be a value. Perhaps some examples can make it more clear:
// Results in true as 'hello' is a textfrom 'hello' is text// Results in true as 'hello' is exactly 'hello'from 'hello' is 'hello'// Results in true as 'hello' is not 'world'from 'hello' is not 'world'// Results in false as 'hello' is not a numberfrom 'hello' is number// Results in true as 'hello' is not a numberfrom 'hello' is not number
match
The match
keyword is especially powerful, as it allows a vastly different execution paths based
on a pattern. In simple terms, match
takes an input value and matches it against a list of
filters. The first filter to match will be evaluated:
param input: valuefrom input match text |> 'input is a text' number |> 'input is a number' |> 'input was something else'
Note that a filter with no input type constraint matches anything.
Just as with filters, input type can be a tuple that deconstructs the values:
param input: value = (a: 1, b: 2)from input match (value1: number, value2: number) |> '{value1} and {value2}' |> 'Unsupported type'
As filters also allows conditions, we can provide a predicate to do even more advanced matching.
Here’s an example:
param valueA = 5param valueB = 3from val match when valueA > valueB |> valueA - valueB when valueA < valueB |> valueB - valueA |> 0
Inferring symbol types
When pattern matching is used against a symbol, filtrera can assume the type of that symbol moving forward.
In the below example, the function’s parameter can be any type. But we can still multiple the value
if it’s a number. Multiply operator would not be allowed on a non-number type, but in this case it’s
allowed as val
must be a number in order to enter the filter.
let myFunc val => val match number |> val * 2 value |> '{val}' nothing |> 'nothing'