# 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
``````