Alternatively, you can write ML99_appl2(ML99_appl(F, v(1)), v(2), v(3)) or ML99_appl3(F, v(1), v(2), v(3)). It works as follows: first, F is applied to v(1), then its arity specifier F_ARITY (e.g., the number of parameters it accepts) is decremented; the same happens with v(2) and v(3). The point here is that each application is already a valid Metalang99 term: you can pass it to higher-order metafunctions, which is quite handy with lists:
Another neat functional facility is function composition. Put simply, ML99_compose(f, g) returns a new metafunction that is identical to first invoking g with user-provided arguments, and then invoking f with the result of invoking g. Take a look at the following macro:
Then this function composition is supplied to ML99_variadicsForEach to achieve the final result.
Partial application and function composition make metafunctions more reusable, which is the essence of functional programming. All higher-order metafunctions in the Metalang99 standard library use partial application under the hood, so you can pass to them both "raw" function-like macro identifiers such as v(F) and partially applied functions as well. Any Metalang99-compliant macro with an arity specifier can be partially applied, and the operation is very cheap.