The “local copy” rule above applies to primitives. Compound types
(struct, array, string) are passed by reference: the function
receives the same underlying data, so changes it makes are visible to the
caller:
voidfill(int[]a) {
a[0] =99; // modifies the caller's array
}
intmain() {
int[] x = [1, 2, 3];
fill(x);
print(x[0]); // 99, the change stuck
return0;
}
The same is true for structs: a function that sets a field changes the
caller’s struct. (See reference semantics.)
This is efficient (no copying) but means a function can mutate what you pass
it. If you don’t want that, the function should avoid writing to its parameter.
When a function returns a struct, the caller receives a reference to the
returned value:
struct Point { int x; int y; }
Point origin() {
Point p;
p.x=0;
p.y=0;
return p;
}
Limitation: array return types aren’t supported. You currently cannot
write int[] makeList() { ... }: an array return type does not parse. The
workaround is to wrap the array in a struct and return that:
struct IntList { int[] items; }
IntList range() {
IntList r;
r.items= [1, 2, 3];
return r;
}
Alternatively, take the array as a reference parameter and fill it in place
(see the fill example above).
No overloading. A function name refers to a single function; you can’t
define two functions with the same name but different parameters.
No default parameter values. Every parameter must be passed explicitly;
the argument count must match (or you get E008).
No nested functions. Functions are declared at the top level, never
inside another function’s body (that’s E011).
Deep recursion uses the call stack. Each call adds a frame; extremely deep
recursion can exhaust the stack, so prefer an iterative version for very large
inputs.