Calling functions

In Quadrate, you call functions by simply writing their name.

Basic calls

fn double(x:i64 -- result:i64) {
    2 *
}

fn main() {
    5 double print nl  // 10
}

No parentheses needed! Just push the arguments, then write the function name.

Chaining functions

Functions naturally chain together:

fn double(x:i64 -- result:i64) {
    2 *
}

fn square(x:i64 -- result:i64) {
    dup *
}

fn add_one(x:i64 -- result:i64) {
    1 +
}

fn main() {
    3 double square add_one print nl
    // 3 -> 6 -> 36 -> 37
}

Each function consumes its inputs and produces outputs for the next.

Multiple arguments

Push all arguments before calling:

fn add3(a:i64 b:i64 c:i64 -- sum:i64) {
    + +
}

fn main() {
    1 2 3 add3 print nl  // 6
}

Stack before call: [1, 2, 3] Stack after call: [6]

Multiple outputs

Capture multiple outputs:

fn minmax(a:i64 b:i64 -- min:i64 max:i64) {
    -> b -> a  // bind parameters
    a b < if {
        a b
    } else {
        b a
    }
}

fn main() {
    10 3 minmax
    // Stack: [3, 10]
    print nl  // 10 (max)
    print nl  // 3 (min)
}

Using outputs

You can immediately use outputs:

fn square(x:i64 -- result:i64) {
    dup *
}

fn main() {
    // Use result in expression
    3 square 4 square + print nl  // 9 + 16 = 25

    // Use result multiple times
    5 square dup print nl print nl  // 25, 25

    // Store result
    7 square -> sqd
    sqd print nl  // 49
}

Recursive calls

Functions can call themselves:

fn factorial(n:i64 -- result:i64) {
    -> n  // bind parameter
    n 1 <= if {
        1
    } else {
        n n 1 - factorial *
    }
}

fn main() {
    5 factorial print nl  // 120
}

Mutual recursion

Functions can call each other:

fn is_even(n:i64 -- result:i64) {
    -> n  // bind parameter
    n 0 == if {
        1
    } else {
        n 1 - is_odd
    }
}

fn is_odd(n:i64 -- result:i64) {
    -> n  // bind parameter
    n 0 == if {
        0
    } else {
        n 1 - is_even
    }
}

fn main() {
    4 is_even print nl  // 1 (true)
    4 is_odd print nl   // 0 (false)
}

Nested calls

Functions can call other functions:

fn inner(x:i64 -- result:i64) {
    1 +
}

fn outer(x:i64 -- result:i64) {
    inner 10 *
}

fn main() {
    5 outer print nl  // (5+1)*10 = 60
}

What's next?

Learn how to organize code into Modules for larger projects.