R 在函数中访问函数中的变量
在R中运行函数时,我在其中运行另一个函数。 我有一个代码在这行:R 在函数中访问函数中的变量,r,function,parameter-passing,R,Function,Parameter Passing,在R中运行函数时,我在其中运行另一个函数。 我有一个代码在这行: f_a <- function(b, c){ return(b + c) } f_e <- function(){ b = 2 c = 2 d = f_a(b, c) print(d) } 有没有一种方法可以通过使用环境、搜索路径或任何其他方式来实现这一点?我鼓励您阅读, 但我认为避免编写大量变量的好方法可能是: get_args_for <- function(fu
f_a <- function(b, c){
return(b + c)
}
f_e <- function(){
b = 2
c = 2
d = f_a(b, c)
print(d)
}
有没有一种方法可以通过使用环境、搜索路径或任何其他方式来实现这一点?我鼓励您阅读, 但我认为避免编写大量变量的好方法可能是:
get_args_for <- function(fun, env = parent.frame(), inherits = FALSE, ..., dots) {
potential <- names(formals(fun))
if ("..." %in% potential) {
if (missing(dots)) {
# return everything from parent frame
return(as.list(env))
}
else if (!is.list(dots)) {
stop("If provided, 'dots' should be a list.")
}
potential <- setdiff(potential, "...")
}
# get all formal arguments that can be found in parent frame
args <- mget(potential, env, ..., ifnotfound = list(NULL), inherits = inherits)
# remove not found
args <- args[sapply(args, Negate(is.null))]
# return found args and dots
c(args, dots)
}
f_a <- function(b, c = 0, ..., d = 1) {
b <- b + 1
c(b = b, c = c, d = d, ...)
}
f_e <- function() {
b <- 2
c <- 2
arg_list <- get_args_for(f_a, dots = list(5))
do.call(f_a, arg_list)
}
> f_e()
b c d
3 2 1 5
像上面这样的东西在R包中可能不起作用,
因为我认为包的函数的封闭环境是被锁定的
或:
一个选项是从调用环境显式获取
a
和b
:
f_a <- function(){
get('b', envir = parent.frame()) + get('c', envir = parent.frame())
}
f_e <- function(){
b = 2
c = 2
d = f_a()
d
}
f_e()
#> [1] 4
不过,这并不是一种真正健壮的代码编写方法,因为它限制了成功调用fa
的可能方式。遵循显式传递变量的代码要容易得多。编辑:
@alistaire建议使用quote
来构造表达式,提出了更进一步的选择,看起来更不难看:
expr_env <- new.env()
expr_env$f_a <- quote(b+c)
expr_env$f_z <- quote(x+y)
f_e<-function(){
b=2
c=2
d=eval( expr_env$f_a)
print(d)
}
另一种方法是只返回一个解析树,然后在“本地”环境中完成对函数的求值。这在我看来是“丑陋的”:
expr\u list您可以将变量分配给全局环境并使用内部函数
f_a <- function(){
return(b + c)
}
f_e <- function(){
assign("b", 2, envir = .GlobalEnv)
assign("c", 2, envir = .GlobalEnv)
d = f_a()
print(d)
}
# > f_e()
# [1] 4
f_a我的f_a中有很多函数,因此这相当麻烦,相当于将变量作为更可行的选项传递。词法范围界定更有意义,因为词法范围界定不是一种选择,而是R的工作方式。无论如何,我强烈建议您重新思考如何构建代码,因为所有这些方法都会引入奇怪的行为,因为它们都与R查找东西的位置有关。实际上,我正在编写一个包,所有这些函数都是包的一部分。我需要不断地在这些功能之间切换,这就是问题所在。我想将所有环境设置为一个主环境,在这个主环境中,我的所有变量对RTH都是可见的。这听起来仍然是一个非常糟糕的方法,这将导致非常难以调试范围bug。在编写大量使用的代码时,冗长不一定是坏事。除了@alistaire的注释外,编写良好的软件模块还具有和。根据您在OP和评论中的描述,最好花些时间重新设计您的函数,使需要更多交互的东西更紧密地结合在同一个函数中,以增加内聚并减少耦合,或者将数据类型抽象成一个更大粒度的对象,可以在函数之间来回传递。同样,我的f_a中有很多函数,因此这将非常麻烦。词法范围对我来说更有意义,尽管这似乎也是一个很好的选择。使用quote
或expression
而不是parse
会(稍微)减少ugly@alistair. 同意并删除无关的return()
。使用全局环境不是我的选项,而是b、c全局常量、参数、对象属性或任意变量。。。?如果您经常需要从某些函数中访问某些变量,那么它应该是一个对象,这难道不是一种强烈的代码味道吗?
f_a <- function() {
with(parent.frame(), {
b <- b + 1
b + c
})
}
f_e <- function() {
b <- 2
c <- 2
d <- f_a()
c(b,d)
}
> f_e()
[1] 3 5
f_a <- function() {
b <- b + 1
b + c
}
f_e <- function() {
b <- 2
c <- 2
# use current environment as enclosing environment for f_a's evaluation
d <- eval(body(f_a), list(), enclos=environment())
c(b=b, d=d)
}
> f_e()
b d
2 5
f_a <- function(){
get('b', envir = parent.frame()) + get('c', envir = parent.frame())
}
f_e <- function(){
b = 2
c = 2
d = f_a()
d
}
f_e()
#> [1] 4
f_a <- function(){
eval(quote(b + c), parent.frame())
}
expr_env <- new.env()
expr_env$f_a <- quote(b+c)
expr_env$f_z <- quote(x+y)
f_e<-function(){
b=2
c=2
d=eval( expr_env$f_a)
print(d)
}
f_e<-function(){
b=2
c=2
d<-local({
b+c
})
print(d)
}
f_e()
[1] 4
expr_list<-function(){ f_a <- quote(b+c)
f_z <- quote(x+y)
list(f_a=f_a,f_z=f_z) }
f_e<-function(){
b=2
c=2
d=eval( (expr_list()$f_a))
print(d)
}
f_a <- function(){
return(b + c)
}
f_e <- function(){
assign("b", 2, envir = .GlobalEnv)
assign("c", 2, envir = .GlobalEnv)
d = f_a()
print(d)
}
# > f_e()
# [1] 4