Function declarations

A function gives a block of statements a name, a list of typed parameters and, optionally, a result type. Calling it runs the block with the arguments bound to the parameters, and the call is worth the value the block returns.

function   = [ attributes ] [ "pub" ] "func" name [ type-parameters ]
             "(" [ parameter { "," parameter } [ "," ] ] ")" [ "->" result ] block
parameter  = name ":" type [ "=" expression ]
           | name ":" type "..."
result     = type | type "!" type | "!" type
func Add(left: int, right: int) -> int {
    return left + right;
}
PartIn AddMeaning
NameAddAn identifier; PascalCase by convention
Parametersleft: int, right: intname: Type each, separated by commas; a trailing comma is allowed
Result type-> intThe type of the value the function returns; omitted when there is none
Body{ return left + right; }A block

Parameters, default values and variadic parameters are described in Parameters. A name in angle brackets after the function name declares a type parameter, which makes the function generic.

Where functions are declared

PlaceDeclares
The top level of a fileA free function of the package's root module
A module A::B { } blockA free function of that module — see Modules
An extend T { } blockA method, constructor, operator or destructor of T
An extern { } blockA foreign function, without a body — see FFI
asm funcA function whose body is assembly — see Assembly

Every other function needs a body. A signature ending in ; is refused:

error: function 'Later' has no body

Declaration order does not matter: a function may call one declared further down the file, or in another file of the package. pub makes a function visible to other packages; see Visibility.

The result

WrittenThe function
no ->Returns nothing. A bare return; leaves early; reaching the closing brace returns
-> TReturns a T. Every path through the body must end in return with a value
-> ()Returns the unit value ()
-> T ! E, -> ! EIs fallible: it returns a T (or nothing) or fails with an E

Several values are returned as a tuple, an absent result as an optional.

func Greet(name: char8[..]) {
    if name.length == 0 {
        return;
    }
    PrintLine("Hello, {}!", name);
}

func Divide(dividend: int, divisor: int) -> (int, int) {
    return (dividend / divisor, dividend % divisor);
}

The compiler checks that a function with a result type returns on every path, and that a function without one never returns a value:

error: function 'Sign' must return a value of type 'int' on every control-flow path
error: 'return' cannot have a value in a function with no return type

Leaving out the result type is not the same as writing -> (). Only a unit-returning function produces a value of type () that can be stored or passed; a call to a function without a result is written as a statement on its own. See return for the statement itself.

Calls

A call is the function's name followed by one argument per parameter, in parentheses and in order. Arguments are evaluated from left to right, then bound to the parameters, and the body runs:

func Note(label: char8[..], value: int) -> int {
    PrintLine("evaluating {}", label);
    return value;
}

func Main() -> int {
    // Prints "evaluating first", then "evaluating second", then 12.
    PrintLine("{}", Pair(Note("first", 1), Note("second", 2)));
    return 0;
}

func Pair(first: int, second: int) -> int {
    return first * 10 + second;
}

A call is an expression of the result type and may appear wherever a value of that type fits — as an argument to another call, in an operator, on the right of a binding.

Each argument must have its parameter's type. Nothing is converted to make a call fit, with one exception: an unsuffixed integer literal takes the integer type of its parameter, so Half(9) works for a uint8 parameter. A function may call itself, directly or through others; each call has its own parameters and locals.

Rules and errors

MistakeError
An argument of another typeargument 1 to 'Square' has type 'float64', but parameter 'value' requires 'int'
Too many or too few argumentscall to 'Square' expects 1 argument, but 2 were provided
A name in the wrong casename 'square' is not defined in this scope, with did you mean 'Square'?
A missing return on some pathfunction 'Sign' must return a value of type 'int' on every control-flow path
A value returned from a function without a result'return' cannot have a value in a function with no return type
A body-less signature outside externfunction 'Later' has no body

Names are case-sensitive. Several functions may share a name when their parameters differ; see Overloading.

See also