Functions are first-order. Both user-defined functions and built-in functions can be passed around as values.

Curly braces are not required for a function declaration if the function body is a single statement.

The f token designates a function definition.

f(.x, .y) { .x + .y } # 2 explicit parameters f() { .x + .y } # no parameters (closure on 2 values) f { .x + .y } # 2 implied parameters

User-defined functions can be called with parentheses, such as .x().

Bulit-in functions can be called with either parentheses or an unbounded argument list, such as split re/[!_]/, "a!b_c" which would split the string "a!b_c" into an array of 3 strings.

Unbounded lists end at a line return, end of file, closing parenthesis, curly brace, or square bracket.

If you do not use a list or parentheses on a function name, it is not a call, but a reference to the function.

Parameters are implied by having no parentheses directly attached to the f token. For example, f (.x - '0') ^ (.x - '0') is a function that has no explicit parameters (1 implied).

Implied parameters are convenient for little functions, such as in the following... sort f .a < .b, [42, 14, 1, 7, -3] # result == [-3, 1, 7, 14, 42]

The implied order of implied parameters is based on the string sort order of their names, not on their order of appearance in the function.

Implied parameters cannot be combined with recursion.

Recursion can be used when the function definition is directly assigned to a variable, such as...

val .fibonacci = f(.x) given .x, .x {
case or 0, 1: .x
default: .fibonacci(.x - 1) + .fibonacci(.x - 2)
}

This example function uses recursion and a single statement (given) without curly braces (braces shown are part of given expression, not for the function).

Note that the map(), fold(), and foldfrom() functions can often be used instead of recursion.

An explicit return can be used, but a function's last value is its implicit return value.

All functions return something, even if it's nothing (null).

Sometimes using parentheses and explicit parameters will give more clarity. For example, I could write...

val .factorial = f fold f .a x .b, series 1 to .n

...but this might be more clearly written as...

val .factorial = f(.n) fold(f .a x .b, series 1 to .n)

- .n not an implied parameter of .factorial()
- fold() using parentheses
- still no parentheses on series(), but it's clear
- still have implied parameters .a and .b on the anonymous function, but it's not confusing