An Anonymous Function (also known as a lambda experssion) is a function definition that is not bound to an identifier. That is, it is a function that is created and used, but never assigned to a variable.
Base R anonymous function syntax
An example in R where anonymous functions are used is in *apply()
family of functions. In the
following example a function is defined which takes one argument, adds one to it,
and then returns it.
sapply(1:2, function(x) x + 1L)
[1] 2 3
Note that this is everything needed for a function definition (formal arugments, a body). It is never actually assigned to a variable, but
used immediately by sapply()
on each element of the given vector.
purrr
’s anonymous function syntax
The purrr package uses the rlang package to help define anonymous functions in a very brief way.
Instead of having to type function(x) {...}
, a function is constructed from a user-specified, one-sided formula. Because purrr/rlang
enforces some constraints on the type of arguments the function definition is very abbreviated:
purrr::map_int(1:2, ~.x + 1L)
[1] 2 3
In the above code, the one-sided formula ~.x + 1
is expanded by rlang::as_function()
into a full function which looks something like:
function(.x) {
.x + 1
}
The advantage of purrr
’s syntax is that it’s very brief. It allows the user
to define functions quickly and with a minimum of characters by:
- Not having to specify
function()
- Pre-defining the arguments to the function to be
.x
(and maybe.y
and some other things), and not giving the user any option to change the defaults.
My issue with purrr
’s anonymous function syntax
I realised recently, that while I like the brevity of the anonymous function
syntax in purrr
/rlang
I felt it a little too constraining because the
two argument names can only be .x
and .y
. This can be a problem as it
can limit the readability of the function quite a bit.
For example, if mapping over vectors of volumes
and surface_areas
, then a map2
call might look like:
ratios <- purrr::map2(volumes, surface_areas, ~.x/.y)
Looking at the anonymous function in isolation, ~.x/.y
isn’t really that informative on what
we are calculating, and it would be nice if we could instead call something like:
ratios <- purrr::map2(volumes, surface_areas, ~vol/area)
Alternatives to purrr
’s anonymous function syntax
I’ve since been on a hunt for an alternative syntax that allows for named arguments
while still retaining some of the brevity of the purrr/rlang
implementation.
I’ve listed all the ones I could find below, and in a future post I will try and compare them to find what syntax is possible and/or useful within the realms of R. Stay tuned…
- Base R
- Built-in support for anonymous functions i.e.
function(x) x + 1
- Built-in support for anonymous functions i.e.
- CRAN
- Non-CRAN package
- Not packaged
- Defunct