Partial application and function composition
Metalang99 supports partial application -- a technique that allows applying arguments to functions separately, not all-at-once. Consider this:
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:
ML99_appl(v(ML99_add), v(3))
is a term representing a function that accepts a single natural number and increments it by 3.ML99_listMap
maps each item in our list with this function.ML99_LIST_EVAL
evaluates the list and pastes all resulting items sequentially.
Without partial application, the situation becomes rather clumsy:
Partial application is especially useful when you want to capture an environment into a closure. With ML99_appl
, it becomes remarkably convenient:
Read more about partial application here.
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:
Here, ML99_braced
is composed with ML99_untuple
:
ML99_untuple
removes brackets from provided arguments:(1, 2, 3)
=>1, 2, 3
.ML99_braced
wraps arguments into curly braces:1, 2, 3
=>{ 1, 2, 3 }
.Overall,
ML99_compose(v(ML99_braced), v(ML99_untuple))
results in(1, 2, 3)
=>{ 1, 2, 3}
.
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.
Last updated