Qu

add

Builtin index · Core maths

result = add(a, b, ...)

Input: a, b, ... · Output: result

What it is

The operators as named functions, so an operation can be passed where a name is what you can pass. Variadic and folded left: add(a, b, c) is a + b + c. Each routes through the very same code the operator does, so broadcasting, units, complex, matrices and every error message are whatever a + b already gives — there is no second set of arithmetic rules that could drift from the first. mul/div follow * and /, which on two matrices mean matrix multiply and solve. subtract, not sub — sub is a keyword (it opens a subroutine), so a builtin of that name could never be called.

Overloads

One call shape — this function is not overloaded.

CodeInputOutputDescription
result = add(a, b, ...)
a —The operators as named functions, so an operation can be passed where a name is what you can pass.
b —Variadic and folded left: add(a, b, c) is a + b + c.
... repeatablenot documented yet
result Num, scalar, Vec, Mat, Complex, CVec, or CMat
Returns whatever the matching operator returns for those arguments: a Num from two scalars, a Vec from a Vec and a scalar, a Mat from two matrices, a Complex/CVec/CMat as soon as either side is complex.

Examples

From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.

function add(a, b)
    return a + b
end function

print("add(2,3) = {add(2,3)}")

square(x) := x^2
print("square(5) = {square(5)}")

function describe(x: num)
    return "num: {x}"
end function

function describe(x: str)
    return "str: {x}"
end function

print(describe(5))
print(describe("hi"))
output
add(2,3) = 5
square(5) = 25
num: 5
str: hi

from tour

How it works

zip/map/dict (§47.4, scoped/shipped 2026-08-26 — see BACKLOG.md "for over collections, zip, map, dict") (see that module's own doc comment); these arms are just the thin wiring into it. get/set/keys/values are plain functions, not new syntax — d.get("k") already works for free via eval_call's existing recv.method(args) == method(recv, args) sugar. The operators as named functions, for the places a NAME is what you can pass: reduce-style folds, a table of operations, a pipeline stage. Each one routes through the very same binop the operator does, so there is no second set of arithmetic rules that could drift from the first -- broadcasting, units, complex, matrices and every error message are whatever a + b already does. mul/div follow * and /, which on two MATRICES mean matrix multiply and solve. elemul/elediv are .* and ./ -- always elementwise, whatever the shapes. That is the one distinction worth having names for, and the reason both families exist rather than just the short ones. Variadic and folded left, so add(a, b, c) reads as the sum it looks like rather than needing to be nested. subtract, not sub: sub is a KEYWORD -- it opens a subroutine -- so a builtin of that name could never be called. The parser rejects sub(a, b) before the interpreter is reached.

From the note above this builtin in the interpreter, where the reasoning was written down as it was built.

See also

subtract, mul, div, pow — documented in the same entry.