Partial function application allows you to modify a function by pre-filling some of the arguments. It is particularly useful in conjunction with functionals and other function operators.

partial(...f, ..., .env = parent.frame(), .lazy = TRUE, .first = TRUE)

Arguments

...f

a function. For the output source to read well, this should be an be a named function.

...

named arguments to ...f that should be partially applied.

.env

the environment of the created function. Defaults to parent.frame() and you should rarely need to modify this.

.lazy

If TRUE arguments evaluated lazily, if FALSE, evaluated when partial is called.

.first

If TRUE, the partialized arguments are placed to the front of the function signature. If FALSE, they are moved to the back. Only useful to control position matching of arguments when the partialized arguments are not named.

Design choices

There are many ways to implement partial function application in R. (see e.g. dots in https://github.com/crowding/ptools for another approach.) This implementation is based on creating functions that are as similar as possible to the anonymous functions that you'd create by hand, if you weren't using partial.

Examples

# Partial is designed to replace the use of anonymous functions for # filling in function arguments. Instead of: compact1 <- function(x) discard(x, is.null) # we can write: compact2 <- partial(discard, .p = is.null) # and the generated source code is very similar to what we made by hand compact1
#> function(x) discard(x, is.null) #> <environment: 0x10fa66e28>
compact2
#> function (...) #> discard(.p = is.null, ...) #> <environment: 0x10fa66e28>
# Note that the evaluation occurs "lazily" so that arguments will be # repeatedly evaluated f <- partial(runif, n = rpois(1, 5)) f
#> function (...) #> runif(n = rpois(1, 5), ...) #> <environment: 0x10fa66e28>
f()
#> [1] 0.17635011 0.11075900 0.93834241 0.84647114 0.57114358 0.67909341 0.08932224
f()
#> [1] 0.2269574 0.4481785 0.1612276 0.1761117 0.1982281 0.3576113 0.1813332
# You can override this by saying .lazy = FALSE f <- partial(runif, n = rpois(1, 5), .lazy = FALSE) f
#> function (...) #> runif(n = 5L, ...) #> <environment: 0x10fa66e28>
f()
#> [1] 0.659083010 0.660253409 0.002400788 0.993446034 0.627489231
f()
#> [1] 0.01463034 0.20517822 0.66307666 0.46374403 0.36034816
# This also means that partial works fine with functions that do # non-standard evaluation my_long_variable <- 1:10 plot2 <- partial(plot, my_long_variable) plot2()
plot2(runif(10), type = "l")