如何解决处理省略号参数中的缺失值 ... in R
如何处理函数参数 ...
中的缺失值?
我有一个通用函数 foo
,它是我想与其他函数(在本例中为 bar
)共享的样板代码。我还希望能够在缺少参数的情况下运行 bar()
。
问题是当我使用 list(...)
时,缺失值会引发错误:
foo = function(...){
list(...)
}
bar = function(name){
foo(name=name)
}
bar("a")
#> $name
#> [1] "a"
bar()
#> Error in foo(name = name): argument "name" is missing,with no default
这里的问题是 list(...)
强制对所有参数求值并在我执行任何 missing
测试之前抛出错误。
我一直在查看 rlang
中的 quosores,但 is_missing
和 quo_is_missing
似乎对 ...
不起作用。
library(rlang)
foo = function(...){
lapply(rlang::enquos(...),is_missing)
}
bar("a")
#> $name
#> [1] FALSE
bar()
#> $name
#> [1] FALSE
foo = function(...){
lapply(rlang::enquos(...),quo_is_missing)
}
bar("a")
#> $name
#> [1] FALSE
bar()
#> $name
#> [1] FALSE
并且 tidy_eval
失败并出现相同的错误:
foo = function(...){
lapply(rlang::enquos(...),eval_tidy)
}
bar("a")
#> $name
#> [1] "a"
bar()
#> Error in FUN(X[[i]],...): argument "name" is missing,with no default
编辑
为了澄清,我想按照 quosore 文档中的本示例中处理缺失值的方式来处理缺失值,但在 ...
中,而无需指定 is_missing
bar
中的每个参数。我从文档中复制了下面的示例:
library(rlang)
fn <- function(arg) enquo(arg)
fn()
#> <quosure>
#> expr: ^
#> env: empty
quo_is_missing(fn())
#> [1] TRUE
解决方法
就像评论所说 - 问题不在于 list(...)
,而在于 bar(name)
。您定义了一个带参数的函数,并且您在不带任何参数的情况下调用该函数,因此出现错误。
如果您想让 bar()
即使缺少参数 name
也能工作,您可以使用 missing()
:
bar = function(name){
if(missing(name)) {
foo()
} else {
foo(name=name)
}
}
现在 bar()
起作用了:
> bar()
list()
编辑后:问题似乎是 list(...)
强制 name
被评估,然后它看到 bar()
没有看到任何 name
。也许捕获对父函数 bar()
的调用在您的情况下有意义?:
foo = function(...) {
as.list(sys.call(1))[-1]
}
bar = function(name){
foo(name=name)
}
> bar()
list()
> bar(name="a")
$name
[1] "a"
,
我找到了解决问题的方法。这不是问题的真正解决方案,而是一种解决方法。它使用 tryCatch
将 ...
中的缺失值转换为 NULL
。如果有人觉得有用,我会在这里发布。
library(rlang)
ellipsis_to_list = function(...){
args_names = call_args_names(match.call())
args_list = list()
range = 0:...length()
range = range[-1]
for(i in seq_along(range)){
v = tryCatch(...elt(i),error=function(e){
if(grepl("missing",e$message)) NULL
else stop(e$message)
})
args_list = c(args_list,list(v))
}
names(args_list) = args_names
args_list
}
foo = function(...){
args_list = ellipsis_to_list(...)
args_list[ ! sapply(args_list,is.null)]
}
boo = function(name){
foo(name=name)
}
boo("a")
#> $name
#> [1] "a"
boo()
#> named list()
由 reprex package (v0.3.0) 于 2021 年 1 月 27 日创建
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。