and*_*ewH 5 nested r function ellipsis parameter-passing
我希望能够在与省略号(...,AKA 点)匹配的函数的参数中传递命名对象,以便在该函数的执行环境或在该环境中执行的函数中普遍可用无论在哪里定义,就好像参数已经在那里输入一样。
我试图这样做,对于一个函数,一个在该函数外部定义的嵌套函数,一个在该函数内部定义的嵌套函数,使用 list2env(),它应该将其参数列表的元素返回到 parent.frame () 环境,我理解为调用环境。因此:
# Ellipsis in nested functions
inner_f1<- function(x){list2env(list(...)[-1L]); x + b}
outer_f <- function(x, ...){
list2env(list(...)[-1L])
in01 <- x + a
inner_f2 <- function(x){list2env(list(...)[-1L]); print(ls()); x + c}
in02 <- inner_f2(x)
in03 <- inner_f1(x)
out <- list(in01, in02, in03)
}
outer_f(x=0, a=1, b=2, c=3)
Run Code Online (Sandbox Code Playgroud)
我在嵌套函数的定义中有和没有...的情况下尝试过这个,但都不起作用。所需的输出是:
$ in01
[1] 1
$ in02
[1] 2
$ in03
[1] 3
Run Code Online (Sandbox Code Playgroud)
“点”下的 R 帮助文件没有提供有关将 ... 值传递给内部函数的信息,它提到从 ... 中获取信息的唯一方法是通过 ..(n) 方法。它指的是“R 简介”,但 par 示例似乎错误地暗示,内部函数拥有自己的......就足够了,尽管 par 代码(未在那里引用)通过以下方式获取内容对 做复杂的事情args = list(...),R 语言定义也描述了 list(...) 方法。我还没有找到惯用语替代(列表(...))[-1],在 R 基础包中经常使用,在任何地方都有正式记录,但无论如何,无论是 this 还是 eval(substitute(alist(...) )) 来自“高级 R”::非标准评估似乎做我想做的。
在 stackoverflow 上有很多关于 ...s 和嵌套函数的问题的答案,但我读到的所有 15 个左右似乎都比我正在寻找的通用方法更专业。
请注意,可用的变量与 列出的变量不同ls()。特别是,ls()不会列出父环境中的变量,但父环境中的变量仍然可用作输入(如果使用 <<-,也可用作输出)。我们假设您只想要可用的变量而不关心ls(). (如果您确实想将变量从外部函数的执行环境实际注入到内部函数中,则将 ... 传递给内部函数,并使用与此处所示的外部函数相同的方法。)以下示例显示,虽然 b是可访问的,但它不会显示在 的输出中ls()。
f1 <- function() {
b <- 1
f2 <- function() {
print(b) # will print the value of b showing b is accessible
print(ls()) # no variables will be shown
}
f2()
}
f1()
Run Code Online (Sandbox Code Playgroud)
给予:
[1] 1
character(0)
Run Code Online (Sandbox Code Playgroud)
现在回到这个问题,这里有一些替代方案:
1)与尝试with:
inner_fun0 <- function() in1
outer_fun <- function(...) with(list(...), {
inner_fun <- function() in1
environment(inner_fun0) <- environment()
list(in1, inner_fun(), inner_fun0())
})
outer_fun(in1 = 7)
Run Code Online (Sandbox Code Playgroud)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
Run Code Online (Sandbox Code Playgroud)
2) list2envlist2env另一种方法是这样使用:
outer_fun2 <- function(...) {
list2env(list(...), environment())
inner_fun <- function() in1
environment(inner_fun0) <- environment()
list(in1, inner_fun(), inner_fun0())
}
outer_fun2(in1 = 7)
Run Code Online (Sandbox Code Playgroud)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
Run Code Online (Sandbox Code Playgroud)
您可以使用从内部函数覆盖父函数中的变量的想法构造其他变体,而无需在父函数外部创建变量
proto 包还可以用于将所有这些重新构建为面向对象的框架。