Functional pattern matching
The functional pattern matching it's an extension of the multiple dispatch feature, and allows us to call a certain function or method using values or expressions as patterns, instead of types.
Example:
func foo((1)) { say "one" }
func foo((2)) { say "two" }
func foo (n) { say n }
foo(1) # calls the first function
foo(2) # calls the second function
foo(3) # calls the third function
Taking advantage of this feature, we can write the Fibonacci function in the following way:
func fib((0)) { 0 }
func fib((1)) { 1 }
func fib (n) { fib(n-1) + fib(n-2) }
say fib(12) # prints: 144
In addition, instead of an expression, we can specify a block of code, which will get called with the value of the argument for checking:
func fib({.is_neg}) { NaN }
func fib({.is_zero}) { 0 }
func fib({.is_one}) { 1 }
func fib(n) { fib(n-1) + fib(n-2) }
say fib(12) # prints: 144
For keeping the value of the argument, we can specify a parameter name in front of the block used for pattern matching:
func fib(n { _ <= 1 }) { n }
func fib(n) { fib(n-1) + fib(n-2) }
say fib(12) # prints: 144
Pattern matching is available for methods as well:
class Ackermann {
method A({ .is_zero }, n) {
n + 1
}
method A(m, (0)) {
self.A(m-1, 1)
}
method A(m, n) {
self.A(m-1, self.A(m, n-1))
}
}
var obj = Ackermann()
say obj.A(3, 2) # prints: 29