Variables
FQL supports two kinds of variable declarations:
letdeclares an immutable variable.vardeclares a mutable variable that can be reassigned later.
let
The let statement assigns the result of an expression to a variable.
The variable is introduced into the scope where the let statement appears.
After a variable is declared with let, it cannot be reassigned.
arrays::append returns a new array and leaves a unchanged. The first two lines after the initial binding intentionally demonstrate invalid assignments.
let bindings often appear where a query needs to refer to an intermediate value, a subquery result, or another computed expression by name.
In this example, numProducts stores the number of items in the user’s cart. The value can then be reused in the returned object without calling length(u.cart) more than once.
let is also useful for assigning the result of a subquery to a variable.
Here, the inner for query finds the friends that belong to the current user. Assigning the result to friends makes the return statement easier to read and allows the same value to be used more than once.
var
The var statement declares a mutable variable. Unlike variables declared with let, variables declared with var can be reassigned.
The general syntax is:
A var variable can be updated later using assignment syntax:
var is suitable for values that change across multiple statements, such as counters, accumulators, or flags.
In this example, total starts at 0 and is updated for each value in numbers.
Destructuring declarations
let and var can bind several names from one object or array. The source expression is evaluated once.
Object entries use the property name as the binding name. Add : to use a different name or a nested pattern. Array entries are positional, and _ explicitly ignores a property or position without reading it. A nested child pattern with no named bindings, such as metadata: [_, _] or details: {}, is ignored as a whole: Ferret does not retrieve or validate that child value. Patterns can be nested recursively and can end with a trailing comma. Empty patterns ({} and []) are valid.
Every named leaf follows the declaration kind. Leaves declared by let are immutable. Leaves declared by var are independently mutable:
Missing properties or elements bind none. Destructuring none also propagates none through nested patterns, while extra source values are ignored. A non-none value reached by the root pattern or by a child pattern needed to produce a binding must support keyed access for an object pattern or indexed access for an array pattern; otherwise execution fails with cannot destructure <Actual> as Object or cannot destructure <Actual> as Array. Explicit empty root patterns still perform this shape check; ignored child patterns do not.
Array holes are not allowed; write _ for each ignored position. Defaults, rest or spread entries, quoted or computed object keys, and conditions are not supported in binding patterns. Destructuring is declaration syntax only: assignments and function parameters still bind one existing target or name.
Compound assignment
FQL supports compound assignment operators that combine an arithmetic operation with assignment. They are shorthand for updating a var variable in place:
| Operator | Equivalent |
|---|---|
a += b |
a = a + b |
a -= b |
a = a - b |
a *= b |
a = a * b |
a /= b |
a = a / b |
Compound assignment operators can only be used with var variables. Using them with let bindings is an error.