R 使用传递给 ...对于命名参数,当...arguments 是命名参数的子字符串

R using arguments passed to ... for named arguments when ... arguments are substring of named argument

提问人:mikeblazanin 提问时间:11/10/2022 更新时间:11/10/2022 访问量:130

问:

我在 R 中的函数中不断遇到这个问题,如果参数(传递给子函数)通过......其名称是 main 函数参数的子字符串,R 将使用 ...参数,即使主函数参数具有默认值:

下面是一个简单的示例:

myfunc <- function(a, b_longer = NULL, ...) {
  print(paste("a =", a))
  if(!is.null(b_longer)) {print(paste("b_longer =", b_longer))}
  if(length(list(...)) > 0) {print("... args detected")}
}

当我跑步时:

> myfunc(a = 5, b_longer = 5)
[1] "a = 5"
[1] "b_longer = 5"
> myfunc(a = 5, c = "hello")
[1] "a = 5"
[1] "... args detected"
> myfunc(a = 5, b = "hello")
[1] "a = 5"
[1] "b_longer = hello"

只要 ...参数的名称仍然是主函数参数名称的子字符串,并且似乎与下划线没有任何关系:

> myfunc(a = 5, b_ = "hello")
[1] "a = 5"
[1] "b_longer = hello"
> myfunc(a = 5, b_l = "hello")
[1] "a = 5"
[1] "b_longer = hello"
> myfunc(a = 5, b_lg = "hello")
[1] "a = 5"
[1] "... args detected"

当默认值为 NA 且非 NULL 时,结果相同:

myfunc2 <- function(a, b_longer = NA, ...) {
  print(paste("a =", a))
  if(!is.na(b_longer)) {print(paste("b_longer =", b_longer))}
  if(length(list(...)) > 0) {print("... args detected")}
}

当我跑步时:

> myfunc2(a = 5, b_longer = 5)
[1] "a = 5"
[1] "b_longer = 5"
> myfunc2(a = 5, c = "hello")
[1] "a = 5"
[1] "... args detected"
> myfunc2(a = 5, b = "hello")
[1] "a = 5"
[1] "b_longer = hello"
> myfunc2(a = 5, b_ = "hello")
[1] "a = 5"
[1] "b_longer = hello"
> myfunc2(a = 5, b_l = "hello")
[1] "a = 5"
[1] "b_longer = hello"
> myfunc2(a = 5, b_lg = "hello")
[1] "a = 5"
[1] "... args detected"

有人对为什么会发生这种情况有任何指示吗?这是默认的 R 行为吗?如果是这样,为什么???

我已经重现了上面的行为,并试图弄清楚这是否只是 R 的一般行为,我需要通过仔细命名我的函数参数来解决,以便它们不是任何可能通过 [...] 传递的参数的超字符串,或者是否有其他方法可以对防止这种错误变量赋值的东西进行编码

R 函数 参数传递 默认值省 略号

评论

2赞 MrFlick 11/10/2022
是的,这是 R 默认行为。R 对参数名称进行部分名称匹配。如果命名参数上有完全的子字符串匹配且没有歧义,则会将值分配给命名参数。它源于自动完成之前的旧时代,当时它试图节省用户在终端上键入的时间。您无法更改此行为。
2赞 MrFlick 11/10/2022
请参见:r 使用部分名称匹配的哪些方法。还相关:stackoverflow.com/questions/25513535/...stackoverflow.com/questions/15264994/...
0赞 r2evans 11/10/2022
也许滑稽的是,基本 R 代码使用(可能在一些地方)截断的参数名称,这意味着许多“方便代码”(代码暂存器,可能没有完全完善)保留在完整的基本函数集中。设置并运行一段时间,以在您使用的任何包(CRAN 或其他)中查看它的证据。我想知道这个选项是否应该是提交到 CRAN 的包的默认值,以开始清理一些不必要的截断(不需要 code-golf)。options(warnPartialMatchArgs=TRUE)
2赞 G. Grothendieck 11/10/2022
dot dot dot dot 之后的任何正式参数都必须完全匹配,因此如果这是您想要的行为,请将 dot dot dot 放在前面。–
0赞 mikeblazanin 11/10/2022
啊,太感谢了!我尝试搜索这种行为,但没有完全正确的术语,现在我做到了

答:

0赞 zephryl 11/10/2022 #1

正如注释中所解释的,这是由于 R 的部分参数匹配。避免这种情况的一种方法是使用不太可能传递给 的 arg 名称。例如,通过用点作为前缀(整洁约定)或使参数全部大写(用于某些基本函数,例如 )。...vapply()

myfunc <- function(.a, .b_longer = NULL, ...) {
  print(paste("a =", .a))
  if(!is.null(.b_longer)) {print(paste("b_longer =", .b_longer))}
  if(length(list(...)) > 0) {print("... args detected")}
}

myfunc(.a = 5, b = "hello")
# "a = 5"
# "... args detected"