Repository navigation
Functions and Closures
Frank edited this page Jan 26, 2026
·
3 revisions
- Named Functions:
fn name(...) { ... } - Function Literals:
fn (...) { ... } - Calls
- Default Parameters
- Arrow Functions
- Rest Parameters
- Closures Example
CupidScript supports named functions and function literals.
Syntax:
fn add(a, b) {
return a + b;
}- Functions are values (callable)
- Parameters are identifiers
- The body is a block
{ ... }
Syntax:
let f = fn(x) { return x + 1; };
print(f(10));Function literals capture the current environment (closure). This is implemented by storing closure = env when the function value is created.
Syntax:
f();
f(1, 2, 3);Argument count must be between the required and total parameter counts. Missing arguments use default values when provided. Too few or too many arguments is a runtime error.
Default values are allowed in function definitions and function literals:
fn greet(name, greeting = "Hello") {
return greeting + ", " + name + "!";
}
let add = fn(a, b = 10) { return a + b; };Rules:
- Required parameters must come before default parameters.
- Defaults are evaluated at call time in the callee’s closure.
- Defaults can reference earlier parameters.
- Passing
nilexplicitly usesnil(it does not trigger the default).
Arrow functions provide a concise syntax with optional implicit return.
let add = fn(a, b) => a + b;
let inc = fn(x) => x + 1;
let block = fn(x) => { return x * 2; };Rules:
-
fn(args) => exprreturns the expression value. -
fn(args) => { ... }uses a block body; explicitreturnis required. - Named functions can also use
=>.
Rest parameters collect extra arguments into a list.
fn log_all(prefix, ...items) {
for item in items {
print(prefix, item);
}
}
log_all(">", "a", "b", "c");Rules:
- Rest parameter must be the last parameter.
-
itemsis a list of any remaining arguments (possibly empty).
fn counter() {
let i = 0;
return fn() {
i = i + 1;
return i;
};
}
let c = counter();
print(c()); // 1
print(c()); // 2i lives in the captured environment and persists across calls.