Укажите аргумент dots при вызове функции, использующей tidyselect, без необходимости указывать предыдущие аргументы - PullRequest
4 голосов
/ 19 марта 2020

Вот упрощенная версия функции, которую я имею в пакете, который использует аргумент ... и tidyselect для выбора переменных:

# this toy function just selects the ... variables
foo <- function(dat = mtcars, ...){
  expr <- rlang::expr(c(...))
  cols_to_select <- tidyselect::eval_select(expr, data = dat)
  dplyr::select(dat, all_of(cols_to_select))
}

Это работает: foo(mtcars, cyl)

Но у моей фактической функции есть больше предшествующих аргументов перед аргументом ..., все со значениями по умолчанию. Утомительно набирать их все в тех случаях, когда я вызываю свою функцию с этими значениями по умолчанию и передаю значение ....

Это то, что я хочу - предположить dat = mtcars - но это не работает:

foo(... = cyl)

Ошибка: имена не должны иметь форму ... или ..j.

Могу ли я изменить любую функцию или вызов, чтобы разрешить прямую спецификацию ...?

1 Ответ

5 голосов
/ 20 марта 2020

Как правило, рекомендуется помещать аргументы со значениями по умолчанию после точек:

f <- function( ..., dat=mtcars )
    dplyr::select( dat, ... )

f(cyl)                 # Works
f(dat=iris, Species)   # Also works

Если ваш API не позволяет размещать именованные аргументы по умолчанию после точки, вот еще одна альтернатива. Обратите внимание, что вам не нужно явно указывать именованные аргументы со значениями по умолчанию. Вы можете просто оставить их «отсутствующими»:

foo(, cyl)    # Same as foo( dat=mtcars, cyl )

Если у вас много аргументов по умолчанию, и вы не хотите вводить кучу запятых в своих вызовах, вы можете использовать purrr::partial(), чтобы записать этот шаблон в автономную функцию:

foo2 <- purrr::partial(foo, ,)  # Effectively partial(foo, dat=mtcars)
foo2(cyl)                       # Works

Если для этого по-прежнему требуется вводить больше запятых, чем вы предпочитаете, вы можете добавить еще один шаг:

foo3 <- purrr::partial( foo, !!!purrr::keep(formals(foo), nzchar) )
foo3(cyl, mpg)                  # Also works
...