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 
close