5.1.12. Function Pointers

This tutorial covers getting a pointer to a named function with @@, the function<> type, calling function pointers, disambiguating overloads with @@<signature>, anonymous functions, and the distinction between function<>, lambda<>, and block<>.

5.1.12.1. Getting a function pointer

Use @@ before a function name to get a pointer to it. The result is a value of type function<>:

def double_it(x : int) : int {
    return x * 2
}

let fn = @@double_it       // type: function<(x:int):int>
print("{fn(5)}\n")         // 10

Function pointers support call syntax — call them like regular functions. invoke() is the explicit alternative:

fn(5)              // call syntax
invoke(fn, 5)      // same result

5.1.12.2. Passing functions as arguments

Declare a parameter with function<> type to accept function pointers:

def apply(f : function<(x:int):int>; value : int) : int {
    return f(value)
}

apply(@@double_it, 7)        // 14
apply(@@negate, 7)           // -7

Only @@-created values can be passed to function<> parameters. Lambdas (@) and blocks ($) are rejected by the compiler.

5.1.12.3. Disambiguating overloads

When multiple functions share a name, specify the signature:

def add(a, b : int) : int { return a + b }
def add(a, b : float) : float { return a + b }

let fn_int   = @@<(a:int;b:int):int> add
let fn_float = @@<(a:float;b:float):float> add

fn_int(3, 4)        // 7
fn_float(1.5, 2.5)  // 4

5.1.12.4. Anonymous functions

@@ can also create a function inline — no name, no capture:

let square <- @@(x : int) : int => x * x
print("{square(6)}\n")        // 36

Multi-line version:

let clamp <- @@(x : int) : int {
    if (x < 0) { return 0 }
    if (x > 100) { return 100 }
    return x
}

Anonymous functions cannot capture outer variables:

var outer = 10
let bad <- @@(x : int) : int => x + outer   // ERROR: can't locate variable

Pass anonymous functions directly to function<> parameters:

apply(@@(x : int) : int => x * x + 1, 8)    // 65

5.1.12.5. function<> vs lambda<> vs block<>

These are three distinct callable types:

Feature

function<> (@@)

lambda<> (@)

block<> ($)

Allocation

None

Heap

Stack

Capture

None

By copy

By reference

Storable

Yes

Yes (move)

No

Returnable

Yes

Yes

No

A function<> parameter accepts only @@ values. A lambda<> parameter accepts only @ values. A block<> parameter accepts any of them (most flexible).

Use function<> for pure transforms with no state. Use lambda<> when you need captured variables. Use block<> for temporary callback parameters.

See also

Functions in the language reference.

Full source: tutorials/language/12_function_pointers.das

Next tutorial: Blocks