Keywords · FUNCTION

FUNCTION

A FUNCTION defines a named block of code which can be called from other places.

Format

The grammar of a single FUNCTION line:

FUNCTION ::= "FUNCTION" [ type ] identifier
type ::= name [ "(" type { " " type } ")" ]
name ::= identifier { "." identifier }
identifier ::= letter { letter | digit }
A FUNCTION keyword is followed by an optional return type and then the function's name.

Usage

A FUNCTION keyword can live inside MODULE, TYPE, and FUNCTION keywords, or at the Root.

Inside a MODULE

Its most common home — the function belongs to a named module and is called through it.

MODULE Format
  FUNCTION Text Wrap
    INPUT Text body
    = body
A function declared inside the Format module.

It becomes part of that module's namespace and is called by its qualified name.

Inside a TYPE

Nested under a type, which acts as a pseudo-module and lends only its name.

TYPE Color
  FIELD Number red
  FUNCTION Text Describe
    INPUT Color value
    = value
A function nested under the Color type.

A free function sharing the type's prefix, not a method — the type merely lends its name.

Inside a FUNCTION

Declared inside another function as a local helper, closed over the enclosing scope.

FUNCTION Text Outer
  INPUT Text body
  FUNCTION Text Inner
    INPUT Text part
    = part
  = body
An inner function declared inside Outer.

With a deeper name it is callable only while the enclosing function is higher up the current call stack.

At the Root

Declared on its own, outside any module or type.

FUNCTION Text Wrap
  INPUT Text body
  = body
A free function declared at the Root.

A free function named directly, with no module prefix.

Can Contain

Its parts appear in this order: the parameter declarations first, then the implementation — either a Program body ending in a single trailing = line whose expression is the return value, or one NATIVE line per target, or both.

Containing an INPUT

A typed parameter, declared before the body. A function takes zero or more, in order — the values every caller must supply.

FUNCTION Text Wrap
  INPUT Text body
  = body
A typed parameter the caller supplies on every call.

Containing a HOLE

A callback parameter, declared after the inputs: a gap the caller fills with a block, each hole carrying its own indented inputs.

FUNCTION Ui.Element Panel
  HOLE Ui.Element content
  = content
A callback parameter the caller fills with a block.

Containing a LET

A derived binding in the body, naming a value computed from the inputs and other bindings and recomputed reactively.

FUNCTION Maths.Real Area
  INPUT Maths.Real radius
  LET Maths.Real area = Maths.Real.Multiply radius radius
  = area
A derived binding computed from the inputs, recomputed reactively.

Containing a CALL

A function called on its own line, run for its effect rather than a value it binds — an effect statement in the body.

FUNCTION Greet
  INPUT Text name
  Console.Write name
A bare call in a function body, run for its effect.

Containing a STATE

A reactive cell declared in the body — local state the function reads and writes.

FUNCTION Ui.Element Counter
  STATE Maths.Integer count = 0
A reactive cell of local state the function reads and writes.

Containing a REVERSE

A write-back block attached to a value in the body, defining what happens when that value is written.

FUNCTION Ui.Element Field
  INPUT Text text
  REVERSE Text textReverse
    SET textState = text
A write-back block defining what happens when the value is written.

Containing a WITH

A block in the body that swaps a module's implementation for another over its indented lines.

FUNCTION Ui.Element Themed
  WITH Logic = Ui.Logic
    LET Ui.Element panel = Ui.Content.Panel content
A block that swaps a module’s implementation over its indented lines.

Containing a NATIVE

A per-target implementation line, one for each platform, given in place of (or as well as) the Program body: the function's host code for that language, written verbatim. A function is all NATIVE lines when it can only be expressed in the host platform, and mixes them with a Program body when the body should serve as the fallback for targets with no native line.

FUNCTION Text ToString
  INPUT Maths.Integer value
  NATIVE js "return String(value)"
A per-target implementation, given in place of a Program body.

Containing a MODULE

A nested module under the function's dotted name — the function acting as a pseudo-module so its name can start longer ones. Its members are visible only while the function is higher up the current call stack.

FUNCTION Text Outer
  MODULE Inner
A nested module under the function’s dotted name, Outer.Inner.

Containing a TYPE

A record or union type declared under the function's dotted name, the function acting as a pseudo-module. Pure naming convenience — an independent type that merely shares the prefix, never a method of the function.

FUNCTION Text Parse
  TYPE Result
    FIELD Text value
A type declared under the function’s dotted name, Parse.Result.

Containing a FUNCTION

A nested function under the dotted name, the function acting as a pseudo-module. A deeper-named function — Outer.Inner — may be called only while Outer is higher up the current call stack, from within Outer's own definition or something it calls. This lets a function prepare context that its deeper-named functions can rely on being present.

FUNCTION Text Outer
  FUNCTION Text Inner
    INPUT Text part
    = part
A nested function under the dotted name, callable as Outer.Inner.

Targets

The same example, rendered to each target.

JavaScript

function Wrap(body, decorate) {
  var decorated = decorate(body);
  return decorated;
}

TypeScript

function Wrap(body: string, decorate: (inner: string) => string): ReactiveValue<string> {
  const decorated = decorate(body);
  return decorated;
}

Dart

static ReactiveValue<String> Wrap(String body, String Function(String inner) decorate) {
  final decorated = decorate(body);
  return decorated;
}

Swift

public static func Wrap(_ body: String, _ decorate: (String) -> String) -> ReactiveValue<String> {
  let decorated = decorate(body)
  return decorated
}

Go

func (FormatStatic) Wrap(body string, decorate func(inner string) string) ReactiveValue[string] {
  decorated := decorate(body)
  return decorated
}

Rust

pub fn Wrap(body: String, decorate: Box<dyn Fn(String) -> String>) -> ReactiveValue<String> {
  let decorated = decorate(body);
  decorated
}

Zig

pub fn Wrap(body: []const u8, decorate: fn (inner: []const u8) []const u8) ReactiveValue([]const u8) {
  const decorated = decorate(body);
  return decorated;
}

JSON

["F", "Wrap", [], [
  ["body", "Text"],
  ["decorate", [[["inner", "Text"]], "Text"]]
], [
  ["=", "decorated", "Text", ["decorate", [], ["body"]]],
  ["=", "__return", "Text", "decorated"]
]]

Related

Parameters are INPUT and HOLE; the body binds values with LET and writes back with REVERSE. A function implemented directly in each target language gives its body per platform with NATIVE lines instead. Back to the language.