Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Arity-Based Dispatch

Ore supports multiple functions with the same name but different parameter counts (arities). The compiler resolves which function to call based on the number of arguments at the call site.

Basic Arity Dispatch

fn add(a: i32, b: i32) -> i32
  a + b

fn add(a: i32, b: i32, c: i32) -> i32
  a + b + c

fn main() -> !i32
  add(1, 2)           // calls add/2 → 3
  add(1, 2, 3)        // calls add/3 → 6
  add(1, 2) + add(1, 2, 3)  // 9

Each arity variant is a completely separate function with its own DefId, type signature, and compiled C name. add/2 compiles to ore_add_2, add/3 compiles to ore_add_3.

Rules

  • Same name + same arity = compile error (duplicate definition)
  • Same name + different arity = allowed (arity dispatch)
  • Non-function definitions (structs, consts, variants) cannot share names

Higher-Order Functions

When passing a function as a value, the compiler infers which arity variant to use from the expected type:

fn apply(f: fn(i32, i32) -> i32, x: i32, y: i32) -> i32
  f(x, y)

fn add(a: i32, b: i32) -> i32 { a + b }
fn add(a: i32, b: i32, c: i32) -> i32 { a + b + c }

fn main() -> !i32
  apply(add, 20, 22)  // apply expects fn(i32, i32) -> i32
                       // only add/2 matches → resolved

If there is only one function with a given name, no disambiguation is needed regardless of context:

fn double(x: i32) -> i32 { x * 2 }

items.map(double)   // only one `double` → no ambiguity

If the compiler cannot determine which arity to use (rare — requires a fully generic parameter with no type constraints), it emits an error:

error: ambiguous function reference: multiple arities available, use in a call to disambiguate

Config Data (Alternative to Optional Parameters)

Ore uses fixed arity. When a function needs several related options, group them into a single data value instead of adding optional parameters.

ServerConfig :: data .{ .port: i32, .host: []const u8, .debug: i32 }

fn start_server(config: ServerConfig) -> i32
  config.port

Aggregate Arguments

For nominal config data, construct the argument explicitly with a headed aggregate:

start_server(ServerConfig.{ .port = 3000, .host = "localhost", .debug = 0 })

If the parameter itself is structural, the expected type can drive an unheaded aggregate:

fn start_server(config: .{ .port: i32, .debug: i32 }) -> i32
  config.port

start_server(.{ .port = 9000, .debug = 1 })

Name Mangling

All non-extern functions include arity in their C name: ore_{name}_{arity}. This ensures distinct C symbols even for same-name functions:

OreC
fn add(a, b)ore_add_2
fn add(a, b, c)ore_add_3
fn main()ore_main_0
extern fn malloc(n)malloc (unchanged)

Extern functions keep their original C names for FFI compatibility.