Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

6. Functions

function_definition = "fn" , NAME , "(" , [ parameter_list ] , ")" , block ;
parameter_list      = NAME , { "," , NAME } , [ "," ] ;

6.1 Definition and binding

fn name(params): defines a function and binds name in the current scope when the definition statement executes. A function defined inside another function is bound in that call's scope and is not visible outside it.

fn square(n):
    return n * n

print(square(9))
# => 81

6.2 Parameters and arity

Parameters are positional. A call must pass exactly as many arguments as the function has parameters, otherwise E0303. There are no default values, variadic parameters, or keyword arguments in Milestone 1. A trailing comma is allowed in both the parameter list and the argument list.

6.3 Return value

return expr ends the call with expr's value. return with nothing, and falling off the end of the body, both yield nil. return outside any function is E0201, reported before the program runs.

fn first_even(xs):
    for x in xs:
        if x % 2 == 0:
            return x
    return nil

print(first_even([1, 3, 4, 7]))
print(first_even([1, 3, 5]))
# => 4
# => nil

6.4 Functions are values

A function is an ordinary value: it can be stored, passed, and returned. type() reports "function" for user functions and builtins alike.

fn apply_twice(f, x):
    return f(f(x))

fn inc(n):
    return n + 1

print(apply_twice(inc, 10))
# => 12

6.5 Closures

A function captures the scope in which it was defined. It sees, and can modify, variables from enclosing functions by the nearest-binding rule (ADR 0011).

fn make_adder(n):
    fn add(x):
        return x + n
    return add

add5 = make_adder(5)
print(add5(1))
print(add5(100))
# => 6
# => 105

The capture is by binding, not by value, so a closure that assigns to a captured variable changes it for every other closure over the same binding:

fn counter():
    count = 0
    fn tick():
        count = count + 1
        return count
    return tick

t = counter()
print(t())
print(t())
# => 1
# => 2

6.6 Recursion

A function may call itself. Call nesting is bounded (see §10.5); unbounded recursion is reported as E0313 rather than crashing.