繁体   English   中英

处理省略号 arguments 中的缺失值…在 R

[英]Deal with missing values in ellipsis arguments … in R

您如何处理 function 的参数...中的缺失值?

我有一个通用的 function foo它是我想与其他功能共享的样板代码(在这种情况下为bar )。 我还希望能够在缺少 arguments 的情况下运行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(...)强制评估所有 arguments 并在我执行任何missing的测试之前引发错误。

我一直在查看rlang中的rlang ,但is_missingquo_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文档但在...中处理它们的方式一样,而不必为bar中的每个参数指定is_missing 我从文档中复制了下面的示例:

library(rlang)
fn <- function(arg) enquo(arg)
fn()
#> <quosure>
#> expr: ^
#> env:  empty
quo_is_missing(fn())
#> [1] TRUE

就像评论说的那样-问题不在于list(...)而在于bar(name) 您定义了一个带参数的 function,并且您在没有任何 arguments 的情况下调用该 function,因此出现错误。

如果你想让bar()工作,即使参数name丢失,你可以使用missing()

bar = function(name){
  if(missing(name)) {
    foo()
  } else {
    foo(name=name)
  }
}

现在bar()工作:

> bar()
list()

编辑后:问题似乎是list(...)强制name被评估,然后它看到bar()没有看到任何name 也许在您的情况下捕获对父 function 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()

代表 package (v0.3.0) 于 2021 年 1 月 27 日创建

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM