【问题标题】:Get environment of function from within the function从函数内部获取函数环境
【发布时间】:2021-08-10 19:58:16
【问题描述】:

我想在一个环境中定义一个函数,它使用来自这个环境的全局变量:

e <- new.env()
e$a <- 1
e$f <- function() a

## e$f()
## Error in e$f() : object 'a' not found

environment(e$f) <- e
e$f()
# [1] 1

到目前为止一切顺利。现在假设我向e 添加另一个(锁定的)绑定:

e$b <- 2
lockBinding("b", e)

我如何(暂时)从f 中解锁此绑定不使用 符号e

e$f <- function() unlockBinding("b", parent.frame())
environment(e$f) <- e
e$f()

不起作用,因为parent.frame 没有正确指向e


我不想直接使用e,因为这会在我克隆环境后立即中断:

e <- new.env()
e$a <- e$b <- 1
lockBinding("b", e)
e$f <- function() unlockBinding("b", e)
environment(e$f) <- e
## e$b <- 3
## Error in e$b <- 3 : cannot change value of locked binding for 'b'

g <- rlang::env_clone(e)
g$f()
e$b <- 3 ## should not work

【问题讨论】:

    标签: r environment


    【解决方案1】:

    proto 包促进了这种事情的发生,避免了最明显的环境混乱。 proto 对象是一个具有类 proto 的环境,它有自己的方法。有关详细信息,请参阅包插图。

    library(proto)
    
    # create proto object containing 3 objects
    p <- proto(a = 1, b = 1, f = function(.) unlockBinding("b", .))
    
    p$lockBinding(sym = "b")  # lock b
    p$b <- 3 # error since p$b is locked
    
    p2 <- as.proto(p$as.list()) # clone p
    p2$b <- 4 # ok since p2 is distinct from p
    
    p$b <- 3  # as expected, this is an error since p$b is locked
    
    ch <- p$proto() # create a child of p
    ch$b  # b is not in ch so it finds it in parent p
    ## [1] 1
    
    ch$b <- 10  # ok since this creates a new b in ch overriding p$b
    
    p$f() # unlock b
    p$b <- 20  # ok
    

    【讨论】:

    • 漂亮,总是喜欢学习新的有用的包。我的用例是我想提供一个沙盒环境,在这个环境中,我闪亮的应用程序中的 R 代码可以“安全地”评估(在某种意义上是安全的,最终用户需要付出一些痛苦才能在脚下开枪)。为此,我重写了包加载函数来记录所有新加载的包,以便在代码为eval'ed 后可以卸载它们。由于这个闪亮应用程序的所有用户无论如何都连接到这台机器,我真的需要一个安全措施,以防止无意中覆盖闪亮应用程序本身的符号。
    • 然而,对于这个用例,proto 包似乎有点矫枉过正(还有另一个依赖项),但将来会用到。
    【解决方案2】:

    好的,找到解决办法了:

    e$f <- function() unlockBinding("b", parent.env(environment()))
    

    应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 2014-07-16
      • 2017-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2020-12-03
      相关资源
      最近更新 更多