exprv4:reference:functions



Functions

Functions package reusable Expr code behind a name.

This chapter describes user-defined functions, function calls, return values, parameters, namespaces, and function references.

Built-in functions such as `print()` and numeric helper functions are listed separately in Built-in functions. Object methods are covered in Methods, this, and properties.


Function Definitions

Define a function with the `function` keyword, a name, a parameter list, and a block body.

function Add(a, b)
{
    return a + b;
}

The function body must be a block.

function Double(value)
{
    value * 2;
}

Function declarations define the function. They do not call it.

function Hello()
{
    print('Hello');
}
 
Hello();

Function names use normal Expr identifier rules. Function parameters are positional names.


Calling Functions

Call a function by writing its name followed by an argument list in parentheses.

Add(2, 3);

Arguments are evaluated before the function body runs.

result = Add(1 + 2, 3 + 4);

The argument count must match the function parameter count.

function Move(x, y, z)
{
    print(x, y, z);
}
 
Move(10, 20, 30);     // valid
Move(10, 20);         // wrong argument count

Empty argument slots and trailing commas are invalid.

Add(, 2);             // invalid
Add(1, );             // invalid

Parameters

Parameters are local variable names created for each function call.

function Scale(value, factor)
{
    value * factor;
}

Arguments are passed as values.

Changing a parameter name inside the function does not change the caller variable with the same value.

function Change(value)
{
    value = 100;
    return value;
}
 
a = 5;
b = Change(a);

After this script, `b` is `100`. The variable `a` is still `5`.

When an object value is passed, the value refers to that object. Object behavior depends on the object type and its methods.


Function Results

A function call produces a value.

Use `return expression;` to exit the function immediately and return a value.

function Clamp01(value)
{
    if(value < 0)
    {
        return 0;
    };
 
    if(value > 1)
    {
        return 1;
    };
 
    return value;
}

If no explicit `return` is used, the function result is the last value produced by the function body.

function Add(a, b)
{
    a + b;
}
 
Add(2, 3);            // 5

`return;` exits immediately without providing a new explicit value.

function Example(a, b)
{
    a + b;
    return;
}

In this case the function keeps the last produced function value. If no earlier value was produced, the result is `none()`.

function Empty()
{
    return;
}
 
Empty().is_none();    // true

Early Return

`return` is commonly used to stop a function as soon as a special case is handled.

function DivideOrNone(a, b)
{
    if(b == 0)
    {
        return none();
    };
 
    return a / b;
}

Code after a `return` is not evaluated.

function Test()
{
    return 1;
    return 2;         // not evaluated
}

Scope Inside Functions

Function parameters are local to the call.

function AddOffset(value)
{
    set offset = 10;
    return value + offset;
}

Use `set` for temporary local variables inside functions.

Plain assignment follows normal Expr name-resolution rules. It updates an existing variable if one is found; otherwise it creates a variable in the current root or object context.

count = 0;
 
function Increment()
{
    count += 1;
    return count;
}

For detailed assignment and scope behavior, see Variables and assignment.


Redefining Functions

Defining a function with the same name replaces the previous user-defined function in the current session or context.

function Mode()
{
    return 'old';
}
 
function Mode()
{
    return 'new';
}
 
Mode();               // 'new'

Use unique, descriptive names for functions that may be included from shared files.


Namespaced Functions

Functions can be defined and called with a namespace prefix.

function MathEx::Clamp(value, low, high)
{
    if(value < low)
    {
        return low;
    };
 
    if(value > high)
    {
        return high;
    };
 
    return value;
}
 
MathEx::Clamp(12, 0, 10);

Namespaces are useful for shared libraries and included files.

An included file can also be imported under an alias. See Include system.


Function Name Resolution

When Expr evaluates a call in the form `Name(…)`, it resolves the name in this order:

  1. A class constructor with that name.
  2. A user-defined function with that name.
  3. A built-in function with that name.

This means a user-defined function can shadow a built-in function with the same name.

function print(value)
{
    return 'shadowed';
}
 
print('test');

Avoid reusing built-in function names unless shadowing is intentional.

Inside object method context, bare calls may resolve to methods on `this` before root or built-in functions. See Methods, this, and properties.


Function References

A function can be used as a value.

function Add(a, b)
{
    return a + b;
}
 
f = Add;
f.call(2, 3);         // 5

Bare identifier value resolution checks variables first, then user-defined function references, then built-in function references.

f = str_spaces;
f.call(4);            // '    '

Function references are object values. User-defined function references and built-in function references can be passed to APIs that expect callbacks.

button.on_click(this.HandleClick);

Method references are explicit object-member references, such as `this.HandleClick`.

Callback behavior depends on the host object or built-in object that receives the reference.


Recursion

A function may call itself.

function Factorial(n)
{
    if(n <= 1)
    {
        return 1;
    };
 
    return n * Factorial(n - 1);
}

Recursive functions must have a terminating condition.

Expr has evaluation-depth limits. Very deep recursion can fail even when the logic is otherwise correct.

For repeated work, prefer `loop`, `while`, or `for` when a loop is simpler.


Common Errors

Wrong Argument Count

A function must be called with the exact number of arguments it declares.

function Add(a, b)
{
    return a + b;
}
 
Add(1);               // wrong argument count
Add(1, 2, 3);         // wrong argument count

Missing Parentheses

A function call requires parentheses.

Add;                  // function reference value
Add();                // function call

Missing Return Value

A function can return `none()` when no value is produced.

function NoValue()
{
}
 
result = NoValue();
result.is_none();     // true

Accidental Built-In Shadowing

A user-defined function can hide a built-in function with the same name.

function abs(value)
{
    return value;
}
 
abs(-5);              // calls user function, not built-in abs

Previous: Control flow

Next: Built-in functions

exprv4/reference/functions.txt · Last modified: by 127.0.0.1

Page Tools