【问题标题】:Is it possible to set a function's environment while runtime in R?是否可以在 R 中运行时设置函数的环境?
【发布时间】:2020-12-17 09:09:46
【问题描述】:

如果你定义函数,它们默认都是Global Environment 的一部分。 我想知道,是否有办法将函数的父环境设置为调用环境(而 运行时 - 一个函数可能在不同的地方被调用!)。因此,在嵌套函数的情况下, 它应该成为可能,只在一个环境中定义一个变量,我希望有一个像

这样的例子
fun1 <- function() {
  # variable "my_env" defined only in this environment
  subfun() # calls subsubfun()
  return(NULL)
} 

exists("my_env", different_environments) 的输出喜欢

# [1] "fun1"
# [1] "===="
# [1] TRUE #     Only here: "here", in this function
# [1] FALSE
# [1] FALSE
# [1] " subfun"
# [1] " ======"
# [1] FALSE
# [1] TRUE #     Only here: "parent environment", in calling function
# [1] FALSE
# [1] "  subsubfun"
# [1] "  ========="
# [1] FALSE
# [1] FALSE
# [1] TRUE #     Only here: "parent-parent environment", in the function calling the function

来自文档?parent.frame

sys.parent 如果 n 为 1,则返回父框架的编号( 默认),如果 n 为 2,则为祖父母,依此类推。另见“注”。
(...) parent.frame(n) 是 sys.frame(sys.parent(n)) (实现效率稍高)。

注意
严格来说,sys.parentparent.frame 指的是上下文 父解释函数。所以内部功能(可能或 可能不会设置上下文,因此可能会或可能不会出现在调用堆栈上) 可能不算数,S3 方法也能做出令人惊讶的事情。 注意惰性求值的效果:这两个函数看 评估它们时的调用堆栈,而不是它们的时间 被称为。将调用作为函数参数传递给它们不太可能 是个好主意。

here 开始的一些示例,它不起作用,因为所有函数都是全局环境的一部分。

subfun0 <- function() {
  e <- parent.frame()
  attr(e, "name") <- "my_env"
  assign("my_env", 1,
         envir = parent.frame(),
         inherits = FALSE, immediate = TRUE)
  return(NULL)
}

subsubfun <- function() {
  print("  subsubfun")
  print("  =========")
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  return(NULL)
}

subfun <- function() {
  print(" subfun")
  print(" ======")
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  subsubfun()
  return(NULL)
}

fun1 <- function() {
  print("fun1")
  print("====")
  subfun0()
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  subfun()
  return(NULL)
}

fun1()

(我刚刚意识到,我对“调用环境”的理解完全错误,我的问题是,我能否让“我的图片”在 R 中工作。)

【问题讨论】:

  • 我不明白你为什么需要它。为什么你不能只将参数传递给你的函数?或者为什么不将环境作为参数传递?
  • @Edo 我想跟踪特殊变量而不需要重写每个函数。我认为这会增加一些很好的灵活性。具体触发是this 非常好的问题...
  • 追踪..?你的意思是? ps:environment&lt;-改变一个函数的环境呢? es: a&lt;-function()i b&lt;-function(){i&lt;-1;a()};b() 返回错误 d&lt;-function(){environment(a)&lt;-environment();i&lt;-1;a()};d() 返回 [1] 1
  • 通过“track”你的意思是你想看看在几个函数之间传递的变量的值是如何随时间变化的?
  • @Edo 你是对的,“跟踪”是误导,我的意思是你可以创建一个变量,你知道“一直”,如果它存在,它必须存在于某个环境中和一个特定的名字。我试过environment() &lt;- rlang::caller_env(),但没有成功。而来自here,我也不确定我的计划是不是不可能了。

标签: r function


【解决方案1】:

使用此代码,您将得到您正在寻找的内容:

subfun0 <- function() {
    e <- parent.frame()
    attr(e, "name") <- "my_env"
    assign("my_env", 1,
                 envir = parent.frame(),
                 inherits = FALSE, immediate = TRUE)
    return(NULL)
}

subsubfun <- function() {
    print("  subsubfun")
    print("  =========")
    print(exists("my_env"))
    print(exists("my_env", parent.frame()))
    print(exists("my_env", parent.frame(2)))
    return(NULL)
}

subfun <- function() {
    print(" subfun")
    print(" ======")
    print(exists("my_env"))
    print(exists("my_env", parent.frame()))
    print(exists("my_env", parent.frame(2)))
    subsubfun()
    return(NULL)
}

fun1 <- function() {
    print("fun1")
    print("====")
    subfun0()
    print(exists("my_env"))
    print(exists("my_env", parent.frame()))
    print(exists("my_env", parent.frame(2)))
    subfun()
    return(NULL)
}

fun1()
[1] "fun1"
[1] "===="
[1] TRUE
[1] FALSE
[1] FALSE
[1] " subfun"
[1] " ======"
[1] FALSE
[1] TRUE
[1] FALSE
[1] "  subsubfun"
[1] "  ========="
[1] FALSE
[1] FALSE
[1] TRUE
NULL

重点是:parent.frame(2)不等于parent.env(parent.frame())

【讨论】:

  • 你能解释一下,为什么“parent.frame(2)不等于parent.env(parent.frame())”?我将文档添加到问题中,对我来说这不是很清楚 - 你的结果当然是! (请参阅我对问题的编辑。)
  • 我相信herehere 你会找到比我能说的更好的解释。特别要注意调用环境和绑定环境的区别
  • 我的意思是“调用 env 并封闭 env”。这就是差异对您的示例很重要的地方。
猜你喜欢
  • 2010-10-09
  • 2019-11-19
  • 1970-01-01
  • 2013-12-18
  • 2014-12-23
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
相关资源
最近更新 更多