any function can be passed around as a normal value. this requires us to create a wrapper around the function, which converts the thin (normal) calling convention of the function into the fat calling convention of a function containing some state. this wrapper is called a "thunk". <<< add = fun (a int, b int) int { return a + b } apply = fun (f fun (a int, b int) int, x int, y int) int { return f(x, y) } main = fun () { var r int = apply(add, 5, 7) } >>> #include "core.c" struct __cat_type_0 { void* state; integer (*call)(void* state, integer, integer); }; integer add(integer a, integer b); integer __cat_thunk_add(void* state, integer, integer); integer apply(struct __cat_type_0 f, integer x, integer y); void catskill_main(void); integer add(integer a, integer b) { return a + b; } integer __cat_thunk_add(void* state, integer a, integer b) { (void)state; return add(a, b); } integer apply(struct __cat_type_0 f, integer x, integer y) { return f.call(f.state, x, y); } void catskill_main(void) { integer r = apply((struct __cat_type_0){ .state = nil, .call = __cat_thunk_add }, 5, 7); } #include "runtime.c"