Skip to content

Extending partial() to comprehend quasiquotation #457

Closed
@egnha

Description

@egnha

It would be nice if partial() were augmented to comprehend quasiquotation, in a way that:

  • preserves the API—maintains the current behavior and argument signature
  • enables partialized arguments to be unquoted and spliced

(Additionally, in the degenerate case where no partialized arguments are supplied, partial() should simply apply as_mapper().)

One possibility is as follows:

library(nofrills)

partial <- function(...f, ..., .env = parent.frame(), .lazy = TRUE, .first = TRUE) {
  ...f <- as_mapper(...f)
  args <- if (.lazy) exprs(...) else lapply(quos(...), eval_tidy)
  
  if (is_empty(args))
    return(...f)
  
  env <- child_env(.env, ...f = ...f)
  if (.first)
    nofrills::fn(... ~ ...f(!!! args, ...), ..env = env)
  else
    nofrills::fn(... ~ ...f(..., !!! args), ..env = env)
}

Remarks:

Some examples showing quasiquotation and compatibility with the current behavior:

# Partialized arguments are lazily evaluated, by default
f <- partial(runif, n = rpois(1, 5))
f
#> function (...) 
#> ...f(n = rpois(1, 5), ...)
#> <environment: 0x10c5338d8>
f() #> [1] 0.5433265
f() #> [1] 0.9367817 0.7762598

# Eager evaluation by setting .lazy = FALSE
f <- partial(runif, n = rpois(1, 5), .lazy = FALSE)
f
#> function (...) 
#> ...f(n = 3L, ...)
#> <environment: 0x10c594ae0>
f() #> [1] 0.9508948 0.8669053 0.4992270
f() #> [1] 0.04073824 0.93821289 0.43544412

# Eager evaluation by unquoting
partial(runif, n = !! rpois(1, 5))
#> function (...) 
#> ...f(n = 4L, ...)
#> <environment: 0x10c5b5aa8>

# Arguments can be spliced eagerly
partial(runif, !!! list(n = rpois(1, 5), max = 2))
#> function (...) 
#> ...f(n = 3L, max = 2, ...)
#> <environment: 0x10c64ef48>
  
# Arguments can be spliced lazily
partial(runif, !!! quos(n = rpois(1, 5), max = 2))
#> function (...) 
#> ...f(n = rpois(1, 5), max = 2, ...)
#> <environment: 0x10c670e30>

(For now, I'm omitting a better print method to focus on the main point.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions