Function Pointers

It is possible to store a function pointer in a variable just like a normal value.

A function pointer is created via the Fn function, which takes a string parameter.

Call a function pointer via the call method.

Short-Hand Notation

Not for native

Native Rust functions cannot use this short-hand notation.

Having to write Fn("foo") in order to create a function pointer to the function foo is a chore, so there is a short-hand available.

A function pointer to any script-defined function within the same script can be obtained simply by referring to the function’s name.

fn foo() { ... }        // function definition

let f = foo;            // function pointer to 'foo'

let f = Fn("foo");      // <- the above is equivalent to this

let g = bar;            // error: variable 'bar' not found

Built-in Functions

The following standard methods operate on function pointers.

name method and propertynonereturns the name of the function encapsulated by the function pointer
is_anonymous method and propertynonedoes the function pointer refer to an anonymous function?
callargumentscalls the function matching the function pointer’s name with the arguments


fn foo(x) { 41 + x }

let func = Fn("foo");       // use the 'Fn' function to create a function pointer

let func = foo;             // <- short-hand: equivalent to 'Fn("foo")'

print(func);                // prints 'Fn(foo)'

let func = fn_name.Fn();    // <- error: 'Fn' cannot be called in method-call style

func.type_of() == "Fn";     // type_of() as function pointer is 'Fn' == "foo"; == 42;         // call a function pointer with the 'call' method

foo(1) == 42;               // <- the above de-sugars to this

call(func, 1);              // normal function call style also works for 'call'

let len = Fn("len");        // 'Fn' also works with registered native Rust functions"hello") == 5;

let fn_name = "hello";      // the function name does not have to exist yet

let hello = Fn(fn_name + "_world");;              // error: function not found - 'hello_world (i64)'

Warning – Global Namespace Only

Because of their dynamic nature, function pointers cannot refer to functions in import-ed modules.

They can only refer to functions defined globally within the script or a built-in function.

import "foo" as f;          // assume there is 'f::do_work()'

f::do_work();               // works!

let p = Fn("f::do_work");   // error: invalid function name

fn do_work_now() {          // call it from a local function

let p = Fn("do_work_now");;                   // works!

Dynamic Dispatch

The purpose of function pointers is to enable rudimentary dynamic dispatch, meaning to determine, at runtime, which function to call among a group.

Although it is possible to simulate dynamic dispatch via a number and a large if-then-else-if statement, using function pointers significantly simplifies the code.

let x = some_calculation();

// These are the functions to call depending on the value of 'x'
fn method1(x) { ... }
fn method2(x) { ... }
fn method3(x) { ... }

// Traditional - using decision variable
let func = sign(x);

// Dispatch with if-statement
if func == -1 {
} else if func == 0 {
} else if func == 1 {

// Using pure function pointer
let func = if x < 0 {
} else if x == 0 {
} else if x > 0 {

// Dynamic dispatch;

// Using functions map
let map = [ method1, method2, method3 ];

let func = sign(x) + 1;

// Dynamic dispatch

Bind the this Pointer

When call is called as a method but not on a function pointer, it is possible to dynamically dispatch to a function call while binding the object in the method call to the this pointer of the function.

To achieve this, pass the function pointer as the first argument to call:

fn add(x) {                 // define function which uses 'this'
    this += x;

let func = add;             // function pointer to 'add';               // error: 'this' pointer is not bound

let x = 41;, 1);            // error: function 'add (i64, i64)' not found

call(func, x, 1);           // error: function 'add (i64, i64)' not found, 1);            // 'this' is bound to 'x', dispatched to 'func'

x == 42;

Beware that this only works for method-call style. Normal function-call style cannot bind the this pointer (for syntactic reasons).