忽略省略号函数中的参数缺失错误
Ignore argument missing error in ellipsis function
由于调用者的尾随逗号,以下代码生成 Error: argument is missing, with no default
。
new_game <- function(...) {
list(...)
}
game <- new_game(
c(1,2,3),
c(1,2),
c(3),
c(2),
c(1), # the comma here is the culprit
)
是否可以通过简单地忽略最后一个“参数”来避免这个错误?
我想这样设计我的函数,因为类似于 Rust 在复合文字中的方式 trailing commas in match statements or structs, or how Go has trailing commas,它可以更轻松地重新排列、添加、删除行以及提交和拉取更改。
原来在 ...
上有一个完整的 documentation,其中可以使用 ...length()
和 ...elt(x)
访问特定参数。我决定将所有内容都放在 try-catch 块中 - 如果抛出错误,可能是由于末尾缺少参数(请注意 missing(...elt(...length()))
不起作用)。
game <- function(...) {
tryCatch(
list(...),
error = function(e) lapply(1:(...length()-1), function(x) ...elt(x))
)
}
或者 rlang
专门针对此用例提供 list2
。
game <- function(...) {
rlang::list2(...)
}
R 是一个奇怪的野兽,因为尽管语法明确允许尾随逗号,但它不像其他语言那样只是 discard/ignore 它们。相反,R 假装传递了一个“缺失的”参数。只要没有触及缺失的论点,那就没问题。我们甚至可以使用这种没有点的情况:
f = function (a, b, c) a + b
因为 c
从未被读取,我们不需要传递它:
f(1, 2) # works
f(1, 2, ) # works, too
也许不是很有用。但以下内容也有效:
g = function (a, b, c) a + b + if (missing(c)) 0 else c
g(1, 2) # 3
g(1, 2, ) # 3
g(1, 2, 3) # 6
…不幸的是,这并不能帮助我们直接捕获...
。
如果不使用现成的解决方案(例如 rlang::list2
),捕获点(允许尾随逗号)的唯一真正方法是处理 未评估的 参数,并手动评估它们(我们可能会想尝试 missing(...elt(...length()))
;可惜 R 不接受)。
有多种获取未计算的点参数的方法。最简单的方法是使用 match.call(expand.dots = FALSE)$...
。这给我们留下了:
new_game = function (...) {
args = match.call(expand.dots = FALSE)$...
nargs = length(args)
if (identical(args[[nargs]], quote(expr = ))) nargs = nargs - 1L
lapply(args[seq_len(nargs)], eval, envir = parent.frame())
}
由于调用者的尾随逗号,以下代码生成 Error: argument is missing, with no default
。
new_game <- function(...) {
list(...)
}
game <- new_game(
c(1,2,3),
c(1,2),
c(3),
c(2),
c(1), # the comma here is the culprit
)
是否可以通过简单地忽略最后一个“参数”来避免这个错误?
我想这样设计我的函数,因为类似于 Rust 在复合文字中的方式 trailing commas in match statements or structs, or how Go has trailing commas,它可以更轻松地重新排列、添加、删除行以及提交和拉取更改。
原来在 ...
上有一个完整的 documentation,其中可以使用 ...length()
和 ...elt(x)
访问特定参数。我决定将所有内容都放在 try-catch 块中 - 如果抛出错误,可能是由于末尾缺少参数(请注意 missing(...elt(...length()))
不起作用)。
game <- function(...) {
tryCatch(
list(...),
error = function(e) lapply(1:(...length()-1), function(x) ...elt(x))
)
}
或者 rlang
专门针对此用例提供 list2
。
game <- function(...) {
rlang::list2(...)
}
R 是一个奇怪的野兽,因为尽管语法明确允许尾随逗号,但它不像其他语言那样只是 discard/ignore 它们。相反,R 假装传递了一个“缺失的”参数。只要没有触及缺失的论点,那就没问题。我们甚至可以使用这种没有点的情况:
f = function (a, b, c) a + b
因为 c
从未被读取,我们不需要传递它:
f(1, 2) # works
f(1, 2, ) # works, too
也许不是很有用。但以下内容也有效:
g = function (a, b, c) a + b + if (missing(c)) 0 else c
g(1, 2) # 3
g(1, 2, ) # 3
g(1, 2, 3) # 6
…不幸的是,这并不能帮助我们直接捕获...
。
如果不使用现成的解决方案(例如 rlang::list2
),捕获点(允许尾随逗号)的唯一真正方法是处理 未评估的 参数,并手动评估它们(我们可能会想尝试 missing(...elt(...length()))
;可惜 R 不接受)。
有多种获取未计算的点参数的方法。最简单的方法是使用 match.call(expand.dots = FALSE)$...
。这给我们留下了:
new_game = function (...) {
args = match.call(expand.dots = FALSE)$...
nargs = length(args)
if (identical(args[[nargs]], quote(expr = ))) nargs = nargs - 1L
lapply(args[seq_len(nargs)], eval, envir = parent.frame())
}