R:使省略号中的命名项在(可能嵌套的)执行环境中可用
R: Make named items in ellipsis available in (maybe nested) execution environment
我希望能够在函数的参数中传递命名对象,这些对象已与省略号(...,AKA 点)相匹配,以便在该函数的执行环境中普遍可用,或者在任何定义的环境中执行的函数,就好像参数是在那里输入的一样。
我尝试这样做,对于一个函数,一个在该函数外部定义的嵌套函数,以及一个在该函数内部定义的嵌套函数,使用 list2env(),它应该 return 元素它的参数列表进入 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)
我在嵌套函数的定义中尝试了使用和不使用 ...,但都不起作用。所需的输出将是:
$ in01
[1] 1
$ in02
[1] 2
$ in03
[1] 3
"dots" 下的 R 帮助文件没有提供有关将 ... 值传递给内部函数的信息,它提到从 ... 中获取信息的唯一方法是通过 ..(n ) 方法。它指的是 "An Introduction to R," 但 par 示例似乎错误地暗示,内部函数拥有自己的 ... 就足够了,尽管 par 代码(未在此处引用)通过复杂的方式获取内容things to args = list(...)
,R 语言定义也描述了 list(...) 方法。我没有找到成语 substitute(list(...))[-1],经常在 R 基础包中使用,在任何地方都有正式记录,但无论如何,这和 eval(substitute(alist(...) )) 来自 "Advanced R"::Nonstandard Evaluation 似乎符合我的要求。
在 Whosebug 上有很多关于 ... 和嵌套函数问题的答案,但我阅读的所有 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()
给予:
[1] 1
character(0)
现在回到这个问题,这里有一些备选方案:
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)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
2) list2env 另一种方法是像这样使用 list2env
:
outer_fun2 <- function(...) {
list2env(list(...), environment())
inner_fun <- function() in1
environment(inner_fun0) <- environment()
list(in1, inner_fun(), inner_fun0())
}
outer_fun2(in1 = 7)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
您可以使用
中的想法构建其他变体
还可以使用 proto 包将所有这些重铸为面向对象的框架。
备选方案:
# note how I add an argument to specify the exact environment:
inner_f1<- function(x, env, ...){
with(env, {list2env(list(...)); x + b})
}
outer_f <- function(x, ...){
# get the "address", i.e. the environment:
here <- environment()
# specify the environment in list2env:
list2env(list(...), envir = here)
in01 <- x + a
inner_f2 <- function(x){list2env(list(...), envir = here); print(ls()); x + c}
# alternatively, use: list2env(list(...), envir = parent.frame(n=2))
in02 <- inner_f2(x)
in03 <- inner_f1(x, here)
out <- list(in01, in02, in03)
return(out)
}
outer_f(x=0, a=1, b=2, c=3)
[1] "x"
[[1]]
[1] 1
[[2]]
[1] 3
[[3]]
[1] 2
本质上,您需要确保正确的 "address" 可用于所有功能。
我希望能够在函数的参数中传递命名对象,这些对象已与省略号(...,AKA 点)相匹配,以便在该函数的执行环境中普遍可用,或者在任何定义的环境中执行的函数,就好像参数是在那里输入的一样。
我尝试这样做,对于一个函数,一个在该函数外部定义的嵌套函数,以及一个在该函数内部定义的嵌套函数,使用 list2env(),它应该 return 元素它的参数列表进入 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)
我在嵌套函数的定义中尝试了使用和不使用 ...,但都不起作用。所需的输出将是:
$ in01
[1] 1
$ in02
[1] 2
$ in03
[1] 3
"dots" 下的 R 帮助文件没有提供有关将 ... 值传递给内部函数的信息,它提到从 ... 中获取信息的唯一方法是通过 ..(n ) 方法。它指的是 "An Introduction to R," 但 par 示例似乎错误地暗示,内部函数拥有自己的 ... 就足够了,尽管 par 代码(未在此处引用)通过复杂的方式获取内容things to args = list(...)
,R 语言定义也描述了 list(...) 方法。我没有找到成语 substitute(list(...))[-1],经常在 R 基础包中使用,在任何地方都有正式记录,但无论如何,这和 eval(substitute(alist(...) )) 来自 "Advanced R"::Nonstandard Evaluation 似乎符合我的要求。
在 Whosebug 上有很多关于 ... 和嵌套函数问题的答案,但我阅读的所有 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()
给予:
[1] 1
character(0)
现在回到这个问题,这里有一些备选方案:
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)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
2) list2env 另一种方法是像这样使用 list2env
:
outer_fun2 <- function(...) {
list2env(list(...), environment())
inner_fun <- function() in1
environment(inner_fun0) <- environment()
list(in1, inner_fun(), inner_fun0())
}
outer_fun2(in1 = 7)
给予:
[[1]]
[1] 7
[[2]]
[1] 7
[[3]]
[1] 7
您可以使用
还可以使用 proto 包将所有这些重铸为面向对象的框架。
备选方案:
# note how I add an argument to specify the exact environment:
inner_f1<- function(x, env, ...){
with(env, {list2env(list(...)); x + b})
}
outer_f <- function(x, ...){
# get the "address", i.e. the environment:
here <- environment()
# specify the environment in list2env:
list2env(list(...), envir = here)
in01 <- x + a
inner_f2 <- function(x){list2env(list(...), envir = here); print(ls()); x + c}
# alternatively, use: list2env(list(...), envir = parent.frame(n=2))
in02 <- inner_f2(x)
in03 <- inner_f1(x, here)
out <- list(in01, in02, in03)
return(out)
}
outer_f(x=0, a=1, b=2, c=3)
[1] "x"
[[1]]
[1] 1
[[2]]
[1] 3
[[3]]
[1] 2
本质上,您需要确保正确的 "address" 可用于所有功能。