partial: Fix a Number of Arguments to a Function

View source: R/partial.R

partialR Documentation

Fix a Number of Arguments to a Function

Description

partial() enables partial application: given a function, it fixes the value of selected arguments to produce a function of the remaining arguments.

departial() undoes the application of partial() by returning the original function.

Usage

partial(..f, ...)

departial(..f)

Arguments

..f

Function.

...

Argument values of ..f to fix, specified by name or position. Captured as quosures. Unquoting and splicing are supported (see ‘Examples’). Argument values may match the ... argument of ..f (if present), but only when specified by name.

Details

Even while partial() truncates formals, it remains compatible with functions that use missing() to test whether a specified argument was supplied in a call. For example, draw3 <- partial(sample, size = 3) works as a function that randomly draws three elements, even though sample() invokes missing(size) and draw3() has the form function(x, replace, prob) {...}.

Because partially applied functions call the original function in an ad hoc environment, impure functions that depend on the calling context as a value, rather than as a lexical scope, may not be amenable to partial(). For example, partial(ls, all.names = TRUE)() is not equivalent to ls(all.names = TRUE), because ls() inspects the calling environment to produce its value, whereas partial(ls, all.names = TRUE)() calls ls(all.names = TRUE) from an (ephemeral) evaluation environment.

Value

partial() returns a function whose formals are a truncation of the formals of ..f (as a closure) by the fixed arguments. NB the original default values do not appear in the formals of a partialized function, but are nonetheless applied when the function is called.

The function partial(..f) is identical to ..f.

In conformance with R's calling convention, fixed argument values are lazy promises. Moreover, when forced, they are tidily evaluated. Lazy evaluation of fixed arguments can be overridden via unquoting, see ‘Examples’.

When ..f is a partially applied function, departial(..f) is the (closure of) the underlying function. For ordinary (non-partially applied) functions, departial(..f) is identical to ..f.

Examples

# Arguments can be fixed by name
draw3 <- partial(sample, size = 3)
draw3(letters)

# Arguments can be fixed by position
draw3 <- partial(sample, , 3)
draw3(letters)

# Use departial() to recover the original function
stopifnot(identical(departial(draw3), sample))

# Lazily evaluate argument values by default
# The value of 'n' is evaluated whenever rnd() is called.
rnd <- partial(runif, n = rpois(1, 5))
replicate(4, rnd(), simplify = FALSE)   # variable length

# Eagerly evaluate argument values with unquoting (`!!`)
# The value of 'n' is fixed when 'rnd_eager' is created.
rnd_eager <- partial(runif, n = !!rpois(1, 5))
len <- length(rnd_eager())
reps <- replicate(4, rnd_eager(), simplify = FALSE)   # constant length
stopifnot(all(vapply(reps, length, integer(1)) == len))

# Mix evaluation schemes by combining lazy evaluation with unquoting (`!!`)
# Here 'n' is lazily evaluated, while 'max' is eagerly evaluated.
rnd_mixed <- partial(runif, n = rpois(1, 5), max = !!sample(10, 1))
replicate(4, rnd_mixed(), simplify = FALSE)

# Arguments to fix can be spliced
args_eager <- list(n = rpois(1, 5), max = sample(10, 1))
rnd_eager2 <- partial(runif, !!!args_eager)
replicate(4, rnd_eager2(), simplify = FALSE)

# Use rlang::exprs() to selectively evaluate arguments to fix
args_mixed <- rlang::exprs(n = rpois(1, 5), max = !!sample(10, 1))
rnd_mixed2 <- partial(runif, !!!args_mixed)
replicate(4, rnd_mixed2(), simplify = FALSE)

# partial() truncates formals by the fixed arguments, omits default values
foo <- function(x, y = x, ..., z = "z") NULL
stopifnot(
  identical(formals(partial(foo)),
            formals(foo)),
  identical(formals(partial(foo, x = 1)),
            formals(function(y, ..., z) NULL)),
  identical(formals(partial(foo, x = 1, y = 2)),
            formals(function(..., z) NULL)),
  identical(formals(partial(foo, x = 1, y = 2, z = 3)),
            formals(function(...) NULL))
)

# Nevertheless, partial() remembers default argument values when called
f <- function(x, y = x) c(x, y)
p <- partial(f, x = 1)
stopifnot(identical(p(), c(1, 1)))


gestalt documentation built on Aug. 22, 2022, 5:08 p.m.