# Functional

## Type

Functional is a collection of types that can hold a function or a closure. To denote the type of function that takes parameters `S, T` (`U`, `V`, ...) and has a return type `R`, the following syntax is used:

``(S, T) -> R``

The return type is mandatory, even if it equals `Unit`. If the function takes no parameters, the parentheses are empty:

``() -> R``

## Assignability

To initialize a variable of a functional type, one can use an anonymous function, non-member function, or a protocol method.

Given

``````function foo(x: Number, y: Text) returns Boolean -> {
return x.toText() == y;
}``````

The following assignments are OK because the types match

``var a: (Number, Text) -> Boolean = foo;``
``var b: (Number) -> Text = function(x: Number) returns Text -> x.toText();``

But these are not

``````var q: (Number, Number) -> Boolean = foo;        // ERROR, 2nd argument type mismatch
var r: (Number, Text, Number) -> Boolean = foo;  // ERROR, missing argument
var s: (Number) -> Boolean = foo;                // ERROR, extra argument
var t: (Number, Text) -> Number = foo;           // ERROR, incorrect return type``````

The functional type `(P_1, P_2, ... P_n) -> R` is assignable to `(Q_1, Q_2, ..., Q_m) -> S` (but not necessarily vice versa) if the following conditions are satistifed:

• `n` = `m`
• for each `i` from `1` to `n`, `Q_i` is assignable to `P_i`
• `R` is assignable to `S`

In other words, one can assign a function that takes contravariant (wider) types as arguments, and returns covariant ( narrower) type.

Given

``````union U { Number, Text }
function fun1(u: U) returns Text -> { return u.toText(); }
function fun2(a: Number) returns U -> { return a; }
function fun3(a: Number) returns Number -> { return a; }
function fun4(a: Number) returns U -> { return a; }``````

The following assignments are OK

``var a: (Number) -> Text = fun1; // OK, Number is narrower than U``
``var b: (Number) -> U = fun3;   // OK, U is wider than Number``

However, `var b: (U) -> U = fun2` is not allowed because `U` is wider than `Number`, and `var d: (Number) -> Number = fun4` is not allowed because `Number` is narrowed than `U`.

Protocol functions may be assigned as well, since they close over `this` ( see Closures).

``````protocol [p] Proto() {
function foo(x: Number) -> {}

permission [p] bar(y: Number) {}

function implicit() -> {
var a: (Number) -> Unit = foo;
}

function explicit() -> {
var a: (Number) -> Unit = function(b: Number) returns Unit -> { this.bar['a'](b); };
}
}``````

Actions cannot be assigned to a functional variable (so a function containing `var a: (Number) -> Unit = bar` is illegal).

## Invocation

To invoke a functional simply supply the comma-separated list of arguments in parentheses as if it was a regular function.

``````struct A {
x: (Number) -> Number
}

function apply(a: A, x: Number, b: (Number, Number) -> Number, y: Number, z: Number) returns Number -> {
return a.x(x) + b(y, z);
}``````