RatMinimal web framework

Functions

A top-level > name declares a function. Bodies indent under the header. Return a value with <<. One-liners collapse the whole body into >> on the same line. Functions live in the global registry, so any page, pup, or service can call them.

A multi-line function

main.rat

Indent the body under the header. A plain name << introduces a local that is scoped to this function - a helper's locals never leak into or clobber its caller's, even when they share a name. (Writes to a name that already exists as server or page state still reach that state; the local rule is only for new names.) Return with a bare <<. Arity is fixed: pass fewer args and the missing slots are null.

> add[a, b]
    [sum] << a + b
    << sum

> server
total: add(4, 7)

One-liner with >>

Shorthand for "return expr"

> name >> expr is the entire function on one line. Use it for pure computations with no locals or statements, just the expression. The reactive graph picks up >> definitions the same way derived fields do.

> double[x] >> x * 2

> server
d: double(21)

Call from a page

No imports or registration, just call

Once declared, the function is in scope everywhere. Call it inside [...] like any other expression. Functions can call each other freely; the resolution order is per-file then global, with builtins last.

> add[a, b] >> a + b

> page
<p> 4 + 7 = [add(4, 7)]
Result

4 + 7 = 11

Lambdas

Anonymous functions for collection helpers

Some builtins (filter, map, reduce) take a callback. Pass an inline lambda with fn >> expr; the eval engine threads it back through the same dispatch path your named functions use.

> server
evens: filter([1, 2, 3, 4], fn[n] >> n % 2 == 0)

Return many values, unpack them

<< a, b returns [a, b]; [x, y] << call() binds both

A return with top-level commas is array sugar: << a, b, c returns [a, b, c]. At the call site, [x, y, z] << call() binds the names positionally - fresh locals, like any bracket binding. A null return leaves every name null (so a (x is null) guard still works); a short array null-fills the missing names and a long one ignores the extras. Keep the named-object form for results that travel; positional unpack is for tight local helpers.

> minmax[xs]
  << first(sort(xs)), last(sort(xs))

> page
[lo, hi] << minmax([4, 1, 9, 2])
<p> low [lo], high [hi]
Result

low 1, high 9

See also Guards and loops · Services · Interpolation