## 5. Functions Functions are user-defined procedures that encapsulate reusable code. They are the primary abstraction mechanism in the language. ### 5.1 What are Functions Functions differ from operators: - **Operators** implement trait methods and are the fundamental building blocks - **Functions** are user-defined procedures that use operators - Operators and functions cannot share names > **Related**: See Section 1 "Operators vs Functions" for a complete explanation of the distinction. ### 5.2 Defining Functions **Syntax**: `(inputs -- outputs) { body } ::name fn` The function signature specifies stack effects (what is consumed and produced), the body contains the implementation, and the name identifies the function. **Examples**: ``` // Simple function - requires Multiplyable trait (Multiplyable -- Multiplyable) { dup * } ::square fn // Use it 5 square // => 25 // Multiple inputs and outputs (Number Number -- Number Number) { over over / swap % } ::divmod fn 10 3 divmod // => 3 1 (quotient remainder) ``` **Function Bodies**: The `{ }` braces contain a TokenString that is parsed as the function body when the function is defined. See Section 5.5 for details on TokenStrings. > **Related**: See Section 10.2 for generic functions with type parameters. ### 5.3 Calling Functions Functions are called by simply writing their name. The postfix notation means arguments must be on the stack before the function name: ``` // Define a function (Number Number -- Number) { + } ::add fn // Call it 3 4 add // => 7 // Chain functions 5 square 2 * // => 50 (square 5, then multiply by 2) ``` **Function Chaining**: Since everything is postfix, functions naturally chain left-to-right: ``` 10 square 2 / 5 + // ((10²) / 2) + 5 = 55 ``` ### 5.4 Recursion Functions can call themselves recursively: ``` (Number -- Number) { dup 1 <= { drop 1 } { dup 1 - factorial * } if } ::factorial fn 5 factorial // => 120 ``` **Stack Considerations**: Recursive functions consume stack space. Deep recursion may cause stack overflow. Consider iterative alternatives for performance-critical code. ### 5.5 Token Strings Token strings are lexed but unparsed code blocks enclosed in `{ }`. They are parsed differently depending on which operator uses them. **Operators that parse TokenStrings:** - `fn` - Parses as function body (code block) - `trait` - Parses as trait definition (method signatures) - `impl` - Parses as trait implementation (method definitions) - `eval` - Parses and executes as code block immediately - `lambda` - Parses as code block, pushes the block as a callable value - `if` - Parses both TokenStrings as code blocks (then/else branches) - `while` - Parses both TokenStrings as code blocks (condition/body) - `for` - Parses TokenString as code block (loop body) - `match` - Parses TokenString as pattern matching arms - `map`, `filter`, `reduce`, `each` - Parse TokenStrings as code blocks for array operations **Examples**: ``` // Function body (parsed by fn) (Number -- Number) { dup * } ::square fn // Conditional branches (parsed by if) x 0 > { "positive" print } { "negative" print } if // Loop body (parsed by while) { dup 10 < } { dup print 1 + } while ``` ### 5.6 Lambda Functions The `lambda` operator converts a TokenString into a callable code block that can be stored and passed around: ``` { dup * } lambda // Creates a callable code block ::square_fn swap // Store reference to the lambda // Later use: 5 square_fn eval // Calls the lambda: pushes 25 ``` **Use Cases**: - Creating first-class functions - Passing code blocks as values - Dynamic dispatch - Higher-order operations **Example with arrays**: ``` // Store a lambda and use it with map { 2 * } lambda ::double swap [1 2 3 4] double map // => [2 4 6 8] ``` > **Related**: See Section 11.1 for the `eval` operator used to execute lambdas. ---