Skip to content

Commit

Permalink
across() gains .call= so that we can control which call governs the c…
Browse files Browse the repository at this point in the history
…aching.

closes #5782
  • Loading branch information
romainfrancois committed Mar 4, 2021
1 parent 7683053 commit d12afe9
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
14 changes: 8 additions & 6 deletions R/across.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#' `{.fn}` to stand for the name of the function being applied. The default
#' (`NULL`) is equivalent to `"{.col}"` for the single function case and
#' `"{.col}_{.fn}"` for the case where a list is used for `.fns`.
#' @param .call Call used by the caching mechanism. This is only useful when `across()`
#' is called from another function, and should mostly just be ignored.
#'
#' @returns
#' `across()` returns a tibble with one column for each column in `.cols` and each function in `.fns`.
Expand Down Expand Up @@ -86,8 +88,8 @@
#'
#' @export
#' @seealso [c_across()] for a function that returns a vector
across <- function(.cols = everything(), .fns = NULL, ..., .names = NULL) {
key <- key_deparse(sys.call())
across <- function(.cols = everything(), .fns = NULL, ..., .names = NULL, .call = sys.call()) {
key <- key_deparse(.call)
setup <- across_setup({{ .cols }}, fns = .fns, names = .names, key = key, .caller_env = caller_env())

vars <- setup$vars
Expand Down Expand Up @@ -147,17 +149,17 @@ across <- function(.cols = everything(), .fns = NULL, ..., .names = NULL) {

#' @rdname across
#' @export
if_any <- function(.cols = everything(), .fns = NULL, ..., .names = NULL) {
df <- across({{ .cols }}, .fns = .fns, ..., .names = .names)
if_any <- function(.cols = everything(), .fns = NULL, ..., .names = NULL, .call = sys.call()) {
df <- across({{ .cols }}, .fns = .fns, ..., .names = .names, .call = .call)
n <- nrow(df)
df <- vec_cast_common(!!!df, .to = logical())
.Call(dplyr_reduce_lgl_or, df, n)
}

#' @rdname across
#' @export
if_all <- function(.cols = everything(), .fns = NULL, ..., .names = NULL) {
df <- across({{ .cols }}, .fns = .fns, ..., .names = .names)
if_all <- function(.cols = everything(), .fns = NULL, ..., .names = NULL, .call = sys.call()) {
df <- across({{ .cols }}, .fns = .fns, ..., .names = .names, .call = .call)
n <- nrow(df)
df <- vec_cast_common(!!!df, .to = logical())
.Call(dplyr_reduce_lgl_and, df, n)
Expand Down
27 changes: 24 additions & 3 deletions man/across.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions man/select.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions tests/testthat/test-across.R
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ test_that("if_any() and if_all() can be used in mutate() (#5709)", {
expect_equal(res$all, c(FALSE, FALSE, FALSE, TRUE))
})

test_that("across() caching not confused when used from if_any() and if_all() (#5782)", {
res <- data.frame(x = 1:3) %>%
mutate(
any = if_any(x, ~ . >= 2) + if_any(x, ~ . >= 3),
all = if_all(x, ~ . >= 2) + if_all(x, ~ . >= 3)
)
expect_equal(res$any, c(0, 1, 2))
expect_equal(res$all, c(0, 1, 2))
})

test_that("if_any() and if_all() respect filter()-like NA handling", {
df <- expand.grid(
x = c(TRUE, FALSE, NA), y = c(TRUE, FALSE, NA)
Expand Down

0 comments on commit d12afe9

Please sign in to comment.