function
A top-level declaration taking at least one parameter and returning a declared type. The body is
either an expression after = or a block whose tail expression is the return value.
function slant_range_m(ground_range_m: float64, altitude_m: float64) -> float64 =
sqrt(ground_range_m * ground_range_m + altitude_m * altitude_m);
function classify(range_m: int32) -> string {
let near: bit = range_m < 5000;
if near then "near" else "far";
}Declarations
A function may be imported by another module. Parameter types and the return type may be any type.
- An empty parameter list is a parse error.
- Parameter names are unique within the declaration.
- The function's name is unique among the file's declarations.
- The body must be assignable to the declared return type.
- Parameters are in scope in the body and nowhere else.
- The function's own name is in scope in its body, so it may call itself. A recursive call types at the declared return type.
The body forms differ only in punctuation. An expression body is = expr;. A block body is a
braced block with no = and no closing semicolon. A block is itself an expression, so = { … }; is
the same body written the other way.
function bearing_delta_deg(from_deg: int32, to_deg: int32) -> int32 = (to_deg - from_deg) % 360;
function countdown(remaining: int32) -> int32 =
if remaining <= 0 then 0 else countdown(remaining - 1);
function sweep_area_m2(diameter_m: float64) -> float64 = {
let radius_m: float64 = diameter_m / 2.0;
3.14159 * radius_m * radius_m;
};Calls
callee(args) is a postfix form. The result type is the callee's declared return type.
- The argument count must match the declared parameter count.
- Arguments match by position, and each must be assignable to its parameter's type.
- A numeric literal argument pins to the parameter's type, so it needs no ascription.
- A call reached through a module alias is written
alias.name(args). - A call result takes further postfix operators, so
make_point(38.9, -77.0).lat_degis one expression.
struct GeoPoint { lat_deg: float64; lon_deg: float64; }
function make_point(lat_deg: float64, lon_deg: float64) -> GeoPoint =
GeoPoint { lat_deg = lat_deg; lon_deg = lon_deg; };
function add(a: int32, b: int32) -> int32 = a + b;
add(40, 2) // => 42
make_point(38.9, -77.0).lat_deg // => 38.9There is no function type: a function cannot be passed as an argument, returned, or held in a let. A
call resolves to a declaration, which is why map and fold take a block body rather than a function
to apply.
Errors
Declaring the same parameter twice
function bearing_delta_deg(from_deg: int32, from_deg: int32) -> int32 = // error: duplicate-param
from_deg % 360;A body that is not the return type
function classify(range_m: int32) -> string = range_m + 1; // error: type-mismatchCalling with the wrong number of arguments
function add(a: int32, b: int32) -> int32 = a + b;
const total: int32 = add(40); // error: call-arg-countAn argument of the wrong type
function add(a: int32, b: int32) -> int32 = a + b;
const total: int32 = add("Viper-1", 2); // error: call-arg-typeRelated
- transform — the same shape restricted to message types, with contextual parameters.
- contract — the other named body, and the one nothing calls.
- builtin functions — the functions already in scope with no declaration.
- block, let, assert — the statements a block body holds.