Higher-order Functions
At a high level, Wyn functions are values, and can be used as any other value. However, to ensure that the compiler is able to compile the higher-order functions efficiently via defunctionalisation, certain type-driven restrictions exist on how functions can be used. These also apply to any record or tuple containing a function (a functional type):
- Arrays of functions are not permitted.
- A function cannot be returned from an
ifexpression. - A loop parameter cannot be a function.
Further, type parameters are divided into non-lifted (bound with an apostrophe, e.g. 't), size-lifted ('~t), and fully lifted ('^t). Only fully lifted type parameters may be instantiated with a functional type. Within a function, a lifted type parameter is treated as a functional type.
See also In-place updates for details on how consumption interacts with higher-order functions.
Function Arity and Partial Application
Wyn functions are not curried by default. Every function has a fixed arity (number of arguments) and must be called with exactly that many arguments. Partial application is not allowed.
def add(x: i32, y: i32) i32 = x + y
-- Valid: fully applied
def result = add(1, 2)
-- INVALID: partial application
def add_one = add(1) -- Error: function requires 2 arguments
This restriction applies uniformly:
- Top-level function definitions
- Lambda expressions
- Built-in functions
- Functions passed as higher-order arguments
The restriction exists to simplify compilation to GPU targets and ensure predictable performance.
Explicit Currying with Placeholder Syntax
When you need to create a partially applied function, use explicit placeholder syntax with $:
def add(x: i32, y: i32) i32 = x + y
-- Create a 2-arity function that calls add with middle arg fixed
def add_with_5 = $add(_, 5, _) -- Produces (i32, i32) -> i32
-- Create a 1-arity function
def add_one = $add(_, 1) -- Produces i32 -> i32
-- Usage
def result = add_one(5) -- Returns 6
The $func(args...) syntax:
_marks placeholder positions that become parameters of the new function- Non-placeholder arguments are captured at the definition site
- The resulting function has arity equal to the number of
_placeholders - The resulting function is itself non-curried (requires all placeholders filled at once)