Home Documentation Templates Examples Showcase GitHub
Theme

Core language · Reusable behaviour & rendering

Functions & fragments.

Functions run Nift's compact statement grammar and optionally return a value. Fragments remain template grammar for reusable rendered output. Both are lexically scoped callables.

Functions

Define a function with @fn(name(args)){...}. Inside its body, declarations, assignments, calls and control flow are statements: they do not need $[...] or template-directive @ prefixes.

@fn(score_class(score)) {
    if(score >= 90) { return "excellent" }
    if(score >= 75) { return "good" }
    if(score >= 50) { return "pass" }
    return "fail"
}

$[score_class(result.score)]

Semicolons are optional, so compact forms such as if(x) { y = 5; return y } are valid.

State, loops and early control flow

@fn(count_visible(items)) {
    count := 0
    for(item : items) {
        if(!item.visible) { continue }
        count = count + 1
    }
    return count
}
@fn(find_featured(items)) {
    for(item : items) {
        if(!item.visible) { continue }
        if(item.featured) { return item }
    }
    return null
}

break exits the innermost loop, continue advances it, and return exits the current function. Loop control cannot escape a callable and affect a caller's loop.

While loops inside functions

@fn(first_power_above(base, limit)) {
    value := 1
    while(value <= limit) {
        value = value * base
    }
    return value
}

Returning a value is optional

A function may return expression, use bare return, or fall through the end. A value-less result is null, which can be tested with expressions such as x != null.

Recursion

@fn(factorial(n)) {
    if(n <= 1) { return 1 }
    return n * factorial(n - 1)
}

Fragments

Fragments are for reusable rendered content, so their bodies keep normal template grammar: @if, @for, @while and $[...].

@fragment(card(item)) {
    @if(!item.visible) { return }
    <article class="card">
        <h2>$[item.title]</h2>
        @if(item.stock <= 0) {
            <p>Out of stock</p>
            return
        }
        <p>$[item.stock] available</p>
    </article>
}

Bare return stops the current fragment. It does not roll back content already rendered, and fragments cannot return an expression value.

Scope

Functions and fragments receive their own child scope. Existing visible mutable bindings can be changed, while declarations created inside the callable disappear when it exits.