A function application f a1 a2 an
applies the function f
to the arguments a1
through an
.
The above syntax is valid where f
is a regular identifier. If the function name is an operator such as *
, then the syntax for application is infix : a1 * a2
. Any operator can be used in prefix position by surrounding it in parentheses: (*) a1 a2
.
All Unison functions are of arity 1. That is, they take exactly one argument. An n-ary function is modeled either as a unary function that returns a further function (a partially applied function) which accepts the rest of the arguments, or as a unary function that accepts a tuple.
Function application associates to the left, so the expression f a b
is the same as (f a) b
. If f
has type T1 -> T2 -> Tn
then f a
is well typed only if a
has type T1
. The type of f a
is then T2 -> Tn
. The type constructor of function types, ->
, associates to the right. So T1 -> T2 -> Tn
parenthesizes as T1 -> (T2 -> TN)
.
The evaluation semantics of function application is applicative order Call-by-Value. In the expression f x y
, x
and y
are fully evaluated in left-to-right order, then f
is fully evaluated, then x
and y
are substituted into the body of f
, and lastly the body is evaluated.
An exception to the evaluation semantics is Boolean expressions, which have non-strict semantics.
Unison supports proper tail calls so function calls in tail position do not grow the call stack.