Skip to content

Commit

Permalink
Better handling of namespaced calls in funs()
Browse files Browse the repository at this point in the history
  • Loading branch information
lionel- committed Mar 22, 2017
1 parent 97a33f3 commit 5d7a061
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
41 changes: 23 additions & 18 deletions R/funs.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@
funs <- function(..., .args = list()) {
dots <- dots_quosures(...)
dots <- map(dots, funs_make_call, args = .args)
new_funs(dots)
}

names(dots) <- names2(dots)
missing_names <- names(dots) == ""
default_names <- map_chr(dots[missing_names], as_name)
names(dots)[missing_names] <- default_names
new_funs <- function(funs) {
names(funs) <- names2(funs)
missing_names <- names(funs) == ""
default_names <- map_chr(funs[missing_names], function(dot) {
quo_text(node_car(f_rhs(dot)))
})
names(funs)[missing_names] <- default_names

class(dots) <- "fun_list"
attr(dots, "have_name") <- any(!missing_names)
dots
class(funs) <- "fun_list"
attr(funs, "have_name") <- any(!missing_names)
funs
}

#' @export
Expand All @@ -59,15 +64,15 @@ as_fun_list.fun_list <- function(.x, ..., .env = base_env()) {
#' @export
as_fun_list.character <- function(.x, ..., .env = base_env()) {
funs <- map(.x, funs_make_call, list(...), env = .env)
funs(!!! funs, .args = list(...))
new_funs(funs)
}
#' @export
as_fun_list.function <- function(.x, ..., .env = base_env()) {
.env <- child_env(.env)
.env$`__dplyr_colwise_fun` <- .x

call <- funs_make_call("__dplyr_colwise_fun", list(...), env = .env)
funs(!! call)
call <- new_language("__dplyr_colwise_fun", quote(.), .args = list(...))
new_funs(list(new_quosure(call, .env)))
}

#' @export
Expand All @@ -94,13 +99,13 @@ funs_make_call <- function(x, args, env = base_env()) {
f <- as_quosureish(x, env)
expr <- get_expr(x)

expr <- switch_type(expr, "funs",
quosure = ,
language = expr,
symbol = substitute(f(.), list(f = expr)),
string = substitute(f(.), list(f = sym(expr)))
)
if (is_symbol(expr) || is_lang(expr, c("::", ":::"))) {
f <- set_expr(f, new_language(expr, quote(.), .args = args))
} else if (is_string(expr)) {
f <- set_expr(f, new_language(sym(expr), quote(.), .args = args))
} else {
f <- lang_modify(f, .args = args)
}

expr <- lang_modify(expr, .args = args)
set_expr(f, expr)
f
}
8 changes: 7 additions & 1 deletion tests/testthat/test-colwise.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ test_that("default names are smallest unique set", {
expect_named(summarise_at(df, vars(x:y), funs(mean)), c("x", "y"))
expect_named(summarise_at(df, vars(x), funs(mean, sd)), c("mean", "sd"))
expect_named(summarise_at(df, vars(x:y), funs(mean, sd)), c("x_mean", "y_mean", "x_sd", "y_sd"))
expect_named(summarise_at(df, vars(x:y), funs(base::mean, stats::sd)), c("x_base::mean", "y_base::mean", "x_stats::sd", "y_stats::sd"))
})

test_that("named arguments force complete namd", {
Expand Down Expand Up @@ -79,7 +80,7 @@ test_that("empty selection does not select everything (#2009, #1989)", {

test_that("error is thrown with improper additional arguments", {
expect_error(mutate_all(mtcars, round, 0, 0), "3 arguments passed")
expect_error(mutate_all(mtcars, mean, na.rm = TRUE, na.rm = TRUE), "Duplicate arguments")
expect_error(mutate_all(mtcars, mean, na.rm = TRUE, na.rm = TRUE), "matched by multiple")
})

test_that("fun_list is merged with new args", {
Expand All @@ -88,6 +89,11 @@ test_that("fun_list is merged with new args", {
expect_identical(funs$fn, ~bar(., baz = "baz"))
})

test_that("funs() works with namespaced calls", {
expect_identical(summarise_all(mtcars, funs(base::mean(.))), summarise_all(mtcars, funs(mean(.))))
expect_identical(summarise_all(mtcars, funs(base::mean)), summarise_all(mtcars, funs(mean(.))))
})


# Deprecated ---------------------------------------------------------

Expand Down

0 comments on commit 5d7a061

Please sign in to comment.