2

我在某个函数中使用了 tidyselection,我必须将第一个参数与省略号连接起来,因为它可能是需要特定处理的特定类。

正常的行为是这样的:

foo = function(x, ...){
    xloc = eval_select(expr(c(x, ...)), data = iris)
    return(xloc)
}
foo(everything())

我希望将其everything()作为默认值xNULL由于某种原因,我不能将其直接放在标题中)。

不幸的是,这种语法是不允许的:

bar = function(x, ...){
    if(is_null(x))
        x=everything() #throws an error
    xloc = eval_select(expr(c(x, ...)), data = iris)
    return(xloc)
}
bar(NULL)
# Error: `everything()` must be used within a *selecting* function.
# i See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.

我试图everything()用我知道的所有“神秘”函数来包装:parse, deparse, call, substitute, quo, sym, enquo, ensym, ... 没有任何效果(你可以在这里看到我没有很好地掌握这些)。

我可以用什么表达式替换我x=everything()的第二个代码块中的行以使该函数起作用?

版本:

  • tidyselect 版本 1.0.0
  • rlang 版本 0.4.5
  • dplyr 版本 0.8.5
4

2 回答 2

2

首先需要通过xvia {{,否则 tidyselect 无法检查参数,导致某些功能无法正常工作。然后你可以给它一个默认值everything()

foo <- function(x = everything(), ...) {
  eval_select(expr(c({{ x }}, ...)), data = iris)
}

foo(everything())
#> Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
#>            1            2            3            4            5

foo()
#> Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
#>            1            2            3            4            5

如果由于某种原因您不能使用默认参数,请everything()手动解散,然后使用以下命令强制它!!

foo <- function(x = NULL, ...) {
  x <- enquo(x)

  if (quo_is_null(x)) {
    x <- expr(everything())
  }

  eval_select(expr(c(!!x, ...)), data = iris)
}
于 2020-03-23T07:52:18.450 回答
1

我们可以everythingeval_select

bar <- function(x, ...){

    xloc <- tidyselect::eval_select(expr(c(x, ...)), data = iris)
    if(length(xloc) == 0) {
     xloc <- tidyselect::eval_select(expr(everything()), data = iris)
      }
    xloc
}



bar(1:2)
#Sepal.Length  Sepal.Width 
#           1            2 
bar(NULL)
#Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#           1            2            3            4            5 

或者我们可以if/elseexpr

bar <- function(x, ...) {

    x1 <-  expr(c(if(is_null(x)) everything() else x, ...))
    tidyselect::eval_select(x1, data = iris)

}

bar(everything())
#Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#           1            2            3            4            5 
bar(NULL)
#Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#           1            2            3            4            5 
于 2020-03-22T20:41:49.893 回答