Pattern matching
The match
operator allows to match values by pattern.
x = 2
print match x {
case 1: "One"
case 2: "Two"
case "str": "String"
case _: "Unknown"
}
x = "str"
match x {
case "": {
println "Empty string"
}
case "str": {
println "String!"
}
}
In this case value and type are checking. If none of case
branches doesn't match, the body of case _
branch will executes.
In addition to the constant values, you can set variable name to case
.
def test(x) = match x {
case a: "case a: " + a
case b: "case b: " + b
case c: "case c: " + c
}
a = 10
b = 20
println test(15) // case c: 15
println test(20) // case b: 20
println test("test") // case c: test
In this case there is two scenarios:
- Variable is already defined. Matching to its value.
- Variable is not defined. Assign matching value to it and executes body of the
case
branch.
In the example above, the interpreter sees the first two branches as:
case 10:
case 20:
For the last branch c
variable is not defined, so assign c = x
and execute body of the case c
branch.
Refinements
case
branch may have additional comparison
def test(x) = match x {
case x if x < 0: "(-∞ .. 0)"
case x if x > 0: "(0 .. +∞)"
case x: "0"
}
println test(-10) // (-∞ .. 0)
println test(0) // 0
println test(10) // (0 .. +∞)
Matching arrays
To compare elements of arrays, the following syntax is used:
case []:
executes if there are no elements in arraycase [a]:
executes if an array contains one elementcase [a :: b]:
executes if an array contains two or more elementscase [a :: b :: c :: d :: e]:
executes if an array contain five or more elements
There are two rules for the last two cases:
- If variables count matches array elements count - all variables are assigned to the value of the array.
match [0, 1, 2] {
case [x :: y :: z]: // x = 0, y = 1, z = 2
}
- If array elements count is greater, then the rest of the array will be assigned to the last variable.
match [0, 1, 2, 3, 4] {
case [x :: y :: z]: // x = 0, y = 1, z = [2, 3, 4]
}
An example of a recursive output array
def arrayRecursive(arr) = match arr {
case [head :: tail]: "[" + head + ", " + arrayRecursive(tail) + "]"
case []: "[]"
case last: "[" + last + ", []]"
}
println arrayRecursive([1, 2, 3, 4, 5, 6, 7]) // [1, [2, [3, [4, [5, [6, [7, []]]]]]]]
Matching array's value
To compare values of array's elements, the following syntax is used:
case (expr1, expr2, expr3):
executes if an array contain 3 elements and first element is equal to expr1 result, second element is equal to expr2 and third element is equal to expr3.case (expr1, _):
executes if an array contain 2 elements and first element is equal to expr1 result and result of the second element is not importand.
FizzBuzz classical problem can be solved using Pattern Matching:
for i = 1, i <= 100, i++ {
println match [i % 3 == 0, i % 5 == 0] {
case (true, false): "Fizz"
case (false, true): "Buzz"
case (true, true): "FizzBuzz"
case _: i
}
}