Partial application and function composition
Last updated
Was this helpful?
Last updated
Was this helpful?
Metalang99 supports -- 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.
maps each item in our list with this function.
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:
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}
.
Read more about partial application .
Another neat functional facility is . 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, is composed with :
Then this function composition is supplied to 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 with an arity specifier can be partially applied, and the operation is very cheap.