Functions
For defining a function, you may use similar syntax known from other languages, such as Scala:
def fib(n: Int): Int =
if (n == 0 || n == 1) 1
else fib(n - 1) + fib(n - 2)
Since fib
is a recursive function, you need to explicitly annotate its return type. Parameters like n
always need to be
annotated with their type.
Calling functions works as you might expect:
fib(5)
Perhaps unusual, you can also call fib
using Effekt’s implementation of Uniform Function Call Syntax
:
5.fib()
Here, the receiver (before the .
) is simply passed as the first argument to the function fib
. If there are no additional arguments, you can also omit the parenthesis:
5.fib.show.println
To define a type polymorphic (generic) function, like the identity function, you need to introduce a type parameter enclosed in square brackets:
def identity[A](x: A): A = x
val a = identity(42)
val b = identity[Int](42)
When calling the function, you may explicitly pass a type argument for each type parameter or let type inference do its job.
There are also nested function definitions. Thus, we also could have defined fib
like this:
def fibNested(n: Int): Int = {
def inner(last: Int, current: Int, count: Int): Int =
if (count == 1) current
else inner(current, last + current, count - 1)
inner(0, 1, n)
}
fibNested(5)
Only at the top level functions can be mutually recursive.
def even(n: Int): Bool = if (n <= 0) true else odd(n - 1)
def odd(n: Int): Bool = if (n <= 0) false else even(n - 1)
7.even