Function Pointers
A function type is fn(Params) -> Ret. Assign a bare function name to get a
pointer-sized value, then call it normally.
use "std/io.cnd";
fn double(v: i32) -> i32 { return v * 2; }
fn triple(v: i32) -> i32 { return v * 3; }
fn apply(f: fn(i32) -> i32, v: i32) -> i32 {
return f(v);
}
fn main() -> i32 {
let f: fn(i32) -> i32 = double;
let d = apply(f, 5);
print(&d, .I32);
let sp: []u8 = " ";
print(&sp, .S);
let t = apply(triple, 5);
print(&t, .I32);
putchar(10);
return 0;
}
$ ./fnptr
10 15
&double works too; it is the same value.
Callbacks
Function types are ordinary values: variables, parameters, struct fields, and
extern signatures.
use "std/io.cnd";
fn on_key(key: u8) {
let v: i32 = key as i32;
print(&v, .I32);
}
fn main() -> i32 {
let handler: fn(u8) = on_key;
handler('a' as u8);
let sp: []u8 = " ";
print(&sp, .S);
handler('b' as u8);
putchar(10);
return 0;
}
$ ./callback
97 98
null function pointers
null is assignable to a function type, and function pointers can be compared
against null.
use "std/io.cnd";
fn main() -> i32 {
let f: fn() = null;
if f == null {
println("not set");
}
return 0;
}
$ ./fnnull
not set
Dispatch tables
A struct of function pointers is a tiny vtable.
use "std/io.cnd";
struct Format {
header: fn() -> []u8;
body: fn(i32) -> []u8;
}
fn csv_header() -> []u8 { return "col,col"; }
fn csv_body(v: i32) -> []u8 { return "csv"; }
fn json_header() -> []u8 { return "{"; }
fn json_body(v: i32) -> []u8 { return "}"; }
fn emit(fmt: *Format, v: i32) {
println(fmt.header());
println(fmt.body(v));
}
fn main() -> i32 {
let csv = Format { header: csv_header, body: csv_body };
let json = Format { header: json_header, body: json_body };
emit(&csv, 1);
emit(&json, 2);
return 0;
}
$ ./dispatch
col,col
csv
{
}