Functions can be declared by using the fun keyword, followed by the name of the declaration, the parameters, the optional return type, and the code that should be executed when the function is called.
The parameters need to be enclosed in parentheses. The return type, if any, is separated from the parameters by a colon (:). The function code needs to be enclosed in opening and closing braces.
Each parameter must have a name, which is the name that the argument value will be available as within the function.
An additional argument label can be provided to require function calls to use the label to provide an argument value for the parameter.
Argument labels make code more explicit and readable. For example, they avoid confusion about the order of arguments when there are multiple arguments that have the same type.
Argument labels should be named so they make sense from the perspective of the function call.
Argument labels precede the parameter name. The special argument label _ indicates that a function call can omit the argument label. If no argument label is declared in the function declaration, the parameter name is the argument label of the function declaration, and function calls must use the parameter name as the argument label.
Each parameter needs to have a type annotation, which follows the parameter name after a colon.
Function calls may provide arguments for parameters which are subtypes of the parameter types.
There is no support for optional parameters, i.e. default values for parameters, and variadic functions, i.e. functions that take an arbitrary amount of arguments.
// Declare a function named `double`, which multiples a number by two.
//
// The special argument label _ is specified for the parameter,
// so no argument label has to be provided in a function call.
//
fun double(_ x: Int): Int {
return x * 2
}
// Call the function named `double` with the value 4 for the first parameter.
//
// The argument label can be omitted in the function call as the declaration
// specifies the special argument label _ for the parameter.
//
double(2) // is `4`
It is possible to require argument labels for some parameters, and not require argument labels for other parameters.
// Declare a function named `clamp`. The function takes an integer value,
// the lower limit, and the upper limit. It returns an integer between
// the lower and upper limit.
//
// For the first parameter the special argument label _ is used,
// so no argument label has to be given for it in a function call.
//
// For the second and third parameter no argument label is given,
// so the parameter names are the argument labels, i.e., the parameter names
// have to be given as argument labels in a function call.
//
fun clamp(_ value: Int, min: Int, max: Int): Int {
if value > max {
return max
}
if value < min {
return min
}
return value
}
// Declare a constant which has the result of a call to the function
// named `clamp` as its initial value.
//
// For the first argument no label is given, as it is not required by
// the function declaration (the special argument label `_` is specified).
//
// For the second and this argument the labels must be provided,
// as the function declaration does not specify the special argument label `_`
// for these two parameters.
//
// As the function declaration also does not specify argument labels
// for these parameters, the parameter names must be used as argument labels.
//
let clamped = clamp(123, min: 0, max: 100)
// `clamped` is `100`
// Declare a function named `send`, which transfers an amount
// from one account to another.
//
// The implementation is omitted for brevity.
//
// The first two parameters of the function have the same type, so there is
// a potential that a function call accidentally provides arguments in
// the wrong order.
//
// While the parameter names `senderAddress` and `receiverAddress`
// are descriptive inside the function, they might be too verbose
// to require them as argument labels in function calls.
//
// For this reason the shorter argument labels `from` and `to` are specified,
// which still convey the meaning of the two parameters without being overly
// verbose.
//
// The name of the third parameter, `amount`, is both meaningful inside
// the function and also in a function call, so no argument label is given,
// and the parameter name is required as the argument label in a function call.
//
fun send(from senderAddress: Address, to receivingAddress: Address, amount: Int) {
// The function code is omitted for brevity.
// ...
}
// Declare a constant which refers to the sending account's address.
//
// The initial value is omitted for brevity.
//
let sender: Address = // ...
// Declare a constant which refers to the receiving account's address.
//
// The initial value is omitted for brevity.
//
let receiver: Address = // ...
// Call the function named `send`.
//
// The function declaration requires argument labels for all parameters,
// so they need to be provided in the function call.
//
// This avoids ambiguity. For example, in some languages (like C) it is
// a convention to order the parameters so that the receiver occurs first,
// followed by the sender. In other languages, it is common to have
// the sender be the first parameter, followed by the receiver.
//
// Here, the order is clear – send an amount from an account to another account.
//
send(from: sender, to: receiver, amount: 100)
The order of the arguments in a function call must match the order of the parameters in the function declaration.
// Declare a function named `test`, which accepts two parameters, named `first` and `second`
//
fun test(first: Int, second: Int) {
// ...
}
// Invalid: the arguments are provided in the wrong order,
// even though the argument labels are provided correctly.
//
test(second: 1, first: 2)
Functions can be nested, i.e., the code of a function may declare further functions.
// Declare a function which multiplies a number by two, and adds one.
//
fun doubleAndAddOne(_ x: Int): Int {
// Declare a nested function which multiplies a number by two.
//
fun double(_ x: Int) {
return x * 2
}
return double(x) + 1
}
doubleAndAddOne(2) // is `5`