7. Functions
7.1 Declaration#
func area(width: float, height: float = 1.0) -> float:
return width * height
func log(message: str):
print(message)Parameters are let bindings. A result type after ->; none means unit. A default is a constant expression or a constructor of one. Every path through a function with a result returns a value; the compiler proves it. A function may be recursive.
7.2 Calls#
let a = area(2.0, 3.0)
let b = area(width = 2.0)
let c = area(2.0, height = 3.0)Arguments are positional, then named; a named argument names a parameter once; a parameter with a default may be omitted. There is no overloading and no variadic parameter; a function that wants any number of things takes a list.
7.3 Methods#
A function declared inside a struct, enum or class is a method; its receiver is self. A method of a struct that assigns to a field of self is a mutating method, and may be called only on a var; the compiler infers this, nothing is written. A method of a class may always assign to var fields. A function declared inside a type without self in its body and called through the type, Point.origin(), is a type function.
7.4 Function values, lambdas and closures#
let positive: func(int) -> bool = (n) => n > 0
let doubled = numbers.map((n) => n * 2)
let counter = func () -> int:
count += 1
return countA named function, a method bound to a receiver, and a lambda are values of a function type. (params) => expression is an expression lambda whose parameter types come from the expected function type; func (params) -> R: with a suite is a block lambda with everything written. A lambda that refers to an outer local captures it: a let value is copied, an object is shared, and a var becomes one cell shared by the scope and every closure that captures it, so a captured counter counts. Closures may be stored, returned and passed anywhere a function value is expected, and live as long as the last reference to them.
A nonfallible function value converts to a function with identical parameters and a fallible result, func(A) -> T to func(A) -> T!. A retained adapter invokes the original callback and returns success; captured cells and receivers keep their normal lifetimes. The opposite conversion is rejected. Fallibility of a block lambda comes from its own written result; an expression lambda uses its expected function type.