R语言 捕获函数中的省略号/三个点;忽略显式提到的参数

iecba09b  于 2023-10-13  发布在  其他
关注(0)|答案(3)|浏览(154)

我想收集一个函数的附加参数的名称(省略号/三个点)。
下面的示例按预期工作

CollectDots <- function(...) {
  as.character(rlang::ensyms(...))
}
CollectDots(A, B, C)
# "A" "B" "C"

但是,如果函数包含一个或多个参数(带/不带默认值),则输出不符合预期。

CollectDots1 <- function(Var1 = NA, ...) {
  as.character(rlang::ensyms(...))
}
CollectDots1(A, B, C) # 1 explicit parameter, returning only B and C
# "B" "C"

CollectDots2 <- function(Var1 = NA, Var2, ...) {
  as.character(rlang::ensyms(...))
}
CollectDots2(A, B, C) # 2 explicit parameters, returning C
# "C"

进一步,如果var1 = 10,为什么下面的函数不打印10并抛出错误

CollectDots3 <- function(Var1 = 10, Var2, ...) {
  print(Var1)
  as.character(rlang::ensyms(...))
}
CollectDots3(A, B, C)
# Error: object 'A' not found

如何只收集提供给函数(...)的附加参数的名称,不包括函数中显式提到的参数?

vhmi4jdf

vhmi4jdf1#

当你定义一个函数时,例如:function(Var1 = NA, ...),你是说函数接受一个命名参数Var1,如果该参数没有任何内容(无论是命名的 * 还是在该位置 *),则使用NA。在CollectDots1()函数中,您只得到“B”和“C”,因为它假定您要指定Var1=A。如果你把点放在前面,在命名的参数之前,你会得到你所期望的。

CollectDots1 <- function(..., Var1 = NA) {
  as.character(rlang::ensyms(...))
}

CollectDots1(A, B, C)
#> [1] "A" "B" "C"

在下面的CollectDots3()中,函数假设您指定Var1=AVar2=B。由于您尝试在没有定义A的情况下打印A,因此会生成错误。

CollectDots3 <- function(Var1 = 10, Var2, ...) {
  print(Var1)
  as.character(rlang::ensyms(...))
}
CollectDots3(A, B, C)

同样,把这三个点放在第一位将给予你所期望的:

CollectDots3 <- function(..., Var1 = 10, Var2) {
  print(Var1)
  as.character(rlang::ensyms(...))
}
CollectDots3(A, B, C)
#> [1] 10
#> [1] "A" "B" "C"

注意,上面的工作只是因为你没有调用Var2,它没有默认值,也没有在函数调用中定义。如果你的函数试图访问Var2而没有命名,那么你会得到一个错误:

CollectDots3 <- function(..., Var1 = 10, Var2) {
  print(Var1)
  cat(Var2)
  as.character(rlang::ensyms(...))
}
CollectDots3(A, B, C)
#> [1] 10
#> Error in CollectDots3(A, B, C): argument "Var2" is missing, with no default

最后,这样做有一个含义(即,把三个点放在前面)--当你调用函数时,你必须总是显式地命名函数的所有命名参数。例如,如果您想使用Var1=20,则必须说CollectDots3(Var1=20)

ou6hu8tu

ou6hu8tu2#

你可以在R中使用match.call来实现

CollectDots1 <- function(Var1 = NA, ...) {
  mc <- as.list(match.call())[-1]
  sapply(mc, as.character) |> unname()
}

CollectDots1(A, B, C)
#> [1] "A" "B" "C"
ymdaylpp

ymdaylpp3#

另一种可能无法完全满足您需求的选择。把它放在你的函数里

elist <- list(...)
dotNames <- names(elist)

相关问题