在调用使用tidyselect的函数时,可以指定dots参数,而不需要指定前面的参数。

6
以下是一个我在使用...参数和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
我正在努力解决一个类似的问题,最终我将我的补充参数放在一个列表中,然后使用 do.call 来解包它们。例如,请参见 https://dev59.com/hXA75IYBdhLWcg3wOGPS#3414202。你可能也会对尝试使用 match.call(expand.dots = FALSE)$\...`` 感兴趣。 - Dan Chaltiel
1个回答

6

通常最好的做法™是在省略号(...)之后放置具有默认值的参数:

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

1
谢谢!目前我决定将...放在最后,原因有两个:首先,如果先插入...会导致当前代码的破坏;其次,相比其他参数,...功能的使用频率较低。我已经点赞了,但我会保留这个问题,以便其他人可以提出关于在最后位置使用...的想法。 - Sam Firke
2
谢谢你的添加-逗号对我来说非常好用! - Sam Firke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接