Search code examples
rtidyevaltidyselect

Using eval_select inside of a nested function


I'm trying to use tidyselect::eval_select() inside a nested function, but am struggling to work out how to pass through user arguments. Inside 1 level of nesting, this works fine:

library(tidyselect)
library(rlang)

my_function <- function(.x, ...) {
 input <- expr(c(...))
 eval_select(input, .x)
}

my_function(mtcars, mpg:cyl, hp, dsp = disp)
#> mpg cyl  hp dsp 
#>   1   2   4   3

However, once I add another level of nesting, I get an error.


my_function <- function(.x, ...){
  input <- enexprs(...)
  my_nested_function(.x, input)
}

my_nested_function <- function(.x, my_expression){
  eval_select(my_expression, .x)
}

my_function(mtcars, mpg:cyl, hp, dsp = disp)
#> Error in `my_nested_function()`:
#> ! Must subset columns with a valid subscript vector.
#> ✖ Subscript has the wrong type `list`.
#> ℹ It must be numeric or character.

Solution

    • Never use enexprs(), always prefer enquos() for capturing expressions that are not yours.

    • Create a c() call around the captured quosures.

    Untested but should work:

    y_function <- function(.x, ...){
      input <- enquos(...)
      my_nested_function(.x, input)
    }
    
    my_nested_function <- function(.x, my_expression){
      eval_select(expr(c(!!!my_expression)), .x)
    }