【问题标题】:Passing variables through environments通过环境传递变量
【发布时间】:2015-11-05 10:12:29
【问题描述】:

我有以下两个功能:

f1<-function(){
txt<-1234
f2(where="txt")
}

f2<-function(where){
foo<-eval(parse(text = where))*2
return(foo)
}

调用 f1() 时,我希望它返回 2468。但是

> f1()
Error in eval(expr, envir, enclos) : object 'txt' not found

我不明白为什么,特别是为什么 f2 不知道 txt。当然它不是在自己的环境中定义的,而是在调用者环境中定义的(在f1中),我认为f1中定义的所有东西都应该对f2可见?

当然,如果在 f1 我有

txt<<-1234

然后

> f1()
[1] 2468

但我宁愿避免全局分配(在实际代码中,我不希望有杂散的全局对象......)

所以问题是,我怎样才能让 txt(在 f1 中定义)对 f2 可见?

谢谢

(如果您想知道,现实生活中的 f2 更复杂,因此传递变量的名称是有意义的;无论如何,它是由其他人编写的函数,我无法控制,所以解决方案应该来自 f1 方面)。

【问题讨论】:

    标签: r


    【解决方案1】:

    1) 问题出在f2,而不是f1,所以应该修复f2。人们通常会定义f2 以显式传递环境。使用此代码f1 将按原样工作。

    f2 <- function(where, envir = parent.frame()) {
      eval(parse(text = where), envir = envir)*2` .  
    }
    

    2) 以下是不太理想的;但是,如果我们无法控制f2,那么我们可以在f1 中执行此操作(现在f2 与问题没有变化):

    f1 <- function() {
       txt <- 1234 
       environment(f2) <- environment()
       f2(where = "txt")
    }
    

    3) 第三种选择是在 f1 中定义 f2:

    f1 <- function(){
       f2 <- function(where) eval(parse(text = where))*2
       txt <- 1234
       f2(where = "txt")
    }
    f1()
    

    【讨论】:

      【解决方案2】:

      eval 中的envir 参数指定为parent.frame()

      f2<-function(where){
          foo<-eval(parse(text = where), envir= parent.frame())*2
         return(foo)
       }
      
      f1()
      #[1] 2468
      

      【讨论】:

      • 它确实有效。但是 f1 方面有没有解决方案(见我原来问题的最后一句话,我在实际代码中对 f2 没有控制)?顺便说一句——为什么?我认为默认行为是查看上游的所有环境(从本地,到调用环境,再到全局......)?
      • 此外 -- eval() 的帮助文件是“Usage:eval(expr, envir = parent.frame() ....”,所以 parent.frame() 应该是默认值,并且应该不需要明确指定它?
      猜你喜欢
      • 2012-08-24
      • 2020-03-05
      • 1970-01-01
      • 2021-11-27
      • 2015-11-19
      • 2021-06-28
      • 1970-01-01
      • 2022-08-16
      • 2020-07-26
      相关资源
      最近更新 更多