Как инициализировать переменную с помощью помощника tidyselect? - PullRequest
2 голосов
/ 22 марта 2020

Я использую tidyselection в некоторой функции, и мне нужно объединить первый аргумент с многоточием, поскольку это может быть специфицированный c класс, который будет нуждаться в специфической c обработке.

нормальное поведение таково:

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

Я хочу иметь everything() в качестве значения по умолчанию, когда x равно NULL ( Я не могу поместить его непосредственно в заголовок по некоторым причинам ).

К сожалению, этот синтаксис недопустим:

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() всеми известными мне функциями "mysti c": parse, deparse, call, substitute, quo, sym, enquo, ensym, ... Ничего не получалось (вы видите, что я не очень хорошо справляюсь с этим).

Каким выражением можно заменить строку x=everything() во втором блоке кода для этой функции?

Версии:

  • tidyselect version 1.0.0
  • rlang version 0.4.5
  • dplyr version 0.8.5

Ответы [ 2 ]

2 голосов
/ 23 марта 2020

Сначала вам нужно передать x через {{, иначе 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)
}
1 голос
/ 22 марта 2020

Мы можем обернуть everything в eval_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/else в expr

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