functions

A function maps input values to output values. In Mech, functions are branch-based and support pattern matching, recursion, and kind annotations.

Syntax

Functions are defined with a signature, one or more guards, and a trailing ..

name(arg1<kind1>, arg2<kind2>, ...) => <return-kind>
  ├ pattern-1 => expression-1
  ├ pattern-2 => expression-2
  └ pattern-n => expression-n.

A function call uses regular call syntax:

name(value1, value2)

The argument name can be added to the call for named arguments:

name(arg1: value1, arg2: value2)

Semantics

  • Branches are matched from top to bottom.

  • The first matching branch is selected.

  • Function bodies are expressions.

  • Functions can call themselves recursively.

  • Calls are expressions, so they can be nested in formulas and broadcast over vectors/matrices.

Defining Functions

Recursive Power

power(x<u64>, n<u64>) <u64>
(*, 0u64) 1u64
(x, n) x*power(x, n-1u64)
.
power(2u64, 8u64)

Recursive Factorial

factorial(n<u64>) <u64>
0u64 1u64
n n*factorial(n-1u64)
.
factorial(10u64)

Recursive Fibonacci

fib(n<u64>) <u64>
0u64 0u64
1u64 1u64
n fib(n-1u64)+fib(n-2u64)
.
fib(10u64)

Calling Functions

Functions are nomally called with the following call syntax:

fxn-name(value1, value2, ...)

Some functions have named arguments, which allow arguments to be passed in any order. In this case, the call syntax is:

fxn-name(arg1: value1, arg2: value2, ...)

Function calls can also broadcast over vectors:

fib(n<u64>) => <u64>
  ├ 0u64 => 0u64
  ├ 1u64 => 1u64
  └ n => fib(n - 1u64) + fib(n - 2u64).

xs := 0u64..=10u64
fib(xs)