在函数内访问函数中的变量 [英] Accessing variables in a function within a function

查看:54
本文介绍了在函数内访问函数中的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在R中运行一个函数时,我在其中运行了另一个函数.我有这样的代码:

When running a function in R, I run another function within it. I have a code on the lines of this:

f_a <- function(b, c){
    return(b + c)
}

f_e <- function(){
    b = 2
    c = 2 
    d = f_a(b, c)
    print(d)
}

这很好.我想做的是不将变量 b,c 传递给函数 f_a .我想做这样的事情(会引发错误)

This works fine. What I'd like to do is not pass the variables b, c to the function f_a. I'd like to do something like this (which throws errors)

f_a <- function(){
    return(b + c)
}

f_e <- function(){
    b = 2
    c = 2
    d = f_a()
    print(d)
}

是否可以使用环境或搜索路径或其他任何方式来做到这一点?

Is there a way to do this using environments or search paths or any other way?

推荐答案

我确实鼓励您阅读有关

I do encourage you to read about lexical scoping, but I think a good approach to avoid writing a lot of variables could be:

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 

默认情况下设置 inherits = FALSE 可确保我们仅从指定的环境中获取变量.我们还可以在调用 get_args_for 时设置 dots = NULL ,以便我们不传递所有变量,但是将省略号留空.

Setting inherits = FALSE by default ensures that we only get variables from the specified environment. We could also set dots = NULL when calling get_args_for so that we don't pass all variables, but leave the ellipsis empty.

尽管如此,它并不完全健壮,因为 dots 只是简单地附加在末尾,如果某些参数未命名,他们最终可能会与职位相匹配.另外,如果在调用中某些值应为 NULL ,很难检测到它.

Nevertheless, it isn't entirely robust, because dots is simply appended at the end, and if some arguments are not named, they could end up matched by position. Also, if some values should be NULL in the call, it wouldn't be easy to detect it.

我强烈建议您不要在R包内使用以下内容.不仅会很丑,您会从R的CMD检查中获得关于未定义的全局变量的大量注释.

I would strongly advise against using these below inside an R package. Not only will it be rather ugly, you'll get a bunch of notes from R's CMD check regarding undefined global variables.

其他选项.

f_a <- function() {
    return(b + c)
}

f_e <- function() {
    b <- 2
    c <- 2
    # replace f_a's enclosing environment with the current evaluation's environment
    environment(f_a) <- environment()
    d <- f_a()
    d
}

> f_e()
[1] 4

在R包中,上述类似内容可能无法正常工作,因为我认为程序包的功能已锁定其封闭环境.

Something like the above probably wouldn't work inside an R package, since I think a package's functions have their enclosing environments locked.

或者:

f_a <- function() {
    with(parent.frame(), {
        b + c
    })
}

f_e <- function() {
    b <- 2
    c <- 2
    f_a()
}

> f_e()
[1] 4

这样,您就不会永久修改其他函数的封闭环境.但是,这两个功能将共享一个环境,所以这样的事情可能会发生:

That way you don't modify the other function's enclosing environment permanently. However, both functions will share an environment, so something like this could happen:

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

在调用内部函数时会修改外部环境中的值.

Where calling the inner function modifies the values in the outer environment.

还有一个更灵活的选择,因为它仅通过使用 eval 临时修改封闭环境.但是,某些R函数可以通过"daRk magic"检测其当前执行环境,并且不能被 eval 欺骗;请参阅

Yet another option that is a bit more flexible, since it only modifies the enclosing environment temporarily by using eval. However, there are certain R functions that detect their current execution environment through "daRk magic", and cannot be fooled by eval; see this discussion.

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 

这篇关于在函数内访问函数中的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆