callback parameters ------------------- C functions that take a callback function pointer often take a "void *user" argument, which is passed to the callback. This could be made type safe by making use of generic types: () sort[T,U](list[T]^ elems; int(U^ context; const T^ a,b) compare; U^ context) { // ... } () main() { typedef Context = (bool reverse); Context ctx = struct(false); list[float] numbers; numbers.init(); numbers.add(@4.5, _); int compare(const Context^ ctx, const float^ a,b) { float x = a^, y = b^; if (ctx^.reverse) { swap(@x, @y, _); } return (if x < y then -1 else if x > y then 1 else 0); } sort(numbers, @compare, @ctx); } If the context parameter is not used, we can use a "void" type: int compare(const ()^ ctx; const float ^a,b) { } sort(numbers, @compare, @()); This could be simplified with some syntactic sugar: () sort[T,U](list[T]^ elems; int(U^ context; const T^ a,b) compare; U^ context) { // ... } () main() { bool reverse = false; list[float] numbers; numbers.init(); numbers.add(@4.5, _); int compare(const locals:type^ ctx, const float^ a,b) { float x = a^, y = b^; if (ctx^.reverse) { swap(@x, @y, _); } return (if x < y then -1 else if x > y then 1 else 0); } sort(numbers, @compare, @locals); } where "locals" is automatically defined like this in every function: namespace locals { // a struct for all the local variables on the stack typedef type = union( (bool reverse); (byte[4]; list[float] numbers); // offset is determined by the compiler ); } // pointer to the local variables on the stack locals:type^ locals;