Here's a simplified version of a function I have in a package that uses the ...
argument and tidyselect
to select variables:
# 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))
}
This works: foo(mtcars, cyl)
But my actual function has more preceding arguments before the ...
argument, all with default values. It's tedious to type them all in cases where I call my function with those default values and pass a value to ...
.
This is what I want - to assume dat = mtcars
- but it does not work:
foo(... = cyl)
Error: Names must not be of the form
...
or..j
.
Can I modify either the function or the call to allow direct specification of ...
?
It is generally a good idea™ to put arguments with default values after the dots:
f <- function( ..., dat=mtcars )
dplyr::select( dat, ... )
f(cyl) # Works
f(dat=iris, Species) # Also works
If your API doesn't allow you to place named default arguments after the dots, here's another alternative. Note that you don't have to specify named arguments with default values explicitly. You can simply leave them "missing":
foo(, cyl) # Same as foo( dat=mtcars, cyl )
If you have a lot of default arguments, and you don't want to keep putting a bunch of commas in your calls, you can make use of purrr::partial()
to capture this pattern into a standalone function:
foo2 <- purrr::partial(foo, ,) # Effectively partial(foo, dat=mtcars)
foo2(cyl) # Works
If that still involves typing more commas than you prefer, you can add one more step:
foo3 <- purrr::partial( foo, !!!purrr::keep(formals(foo), nzchar) )
foo3(cyl, mpg) # Also works
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With