Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending partial() to comprehend quasiquotation #457

Closed
egnha opened this issue Feb 6, 2018 · 1 comment
Closed

Extending partial() to comprehend quasiquotation #457

egnha opened this issue Feb 6, 2018 · 1 comment
Labels
adverb 📚 feature a feature request or enhancement

Comments

@egnha
Copy link
Contributor

egnha commented Feb 6, 2018

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.)

@egnha
Copy link
Contributor Author

egnha commented Feb 7, 2018

Erratum: the approach in #349 is viable after all. (Explanation there.)

@hadley hadley added the feature a feature request or enhancement label May 5, 2018
@lionel- lionel- added adverb 📚 breaking change ☠️ API change likely to affect existing code and removed breaking change ☠️ API change likely to affect existing code labels Nov 16, 2018
lionel- added a commit to lionel-/lowliner that referenced this issue Dec 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adverb 📚 feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants