强制R函数调用是自给自足的

时间:2017-08-25 21:42:56

标签: r scoping environments

我正在寻找一种方法来调用不受.GlobalEnv中其他对象影响的函数。

看看下面的两个函数:

y = 3
f1 = function(x) x+y

f2 = function(x) {
   library(dplyr)
   x %>%
       mutate(area = Sepal.Length *Sepal.Width) %>%
       head()
}

在这种情况下:

  • f1(5)应该失败,因为y未在函数范围中定义
  • f2(iris)应该通过,因为该函数不引用其范围之外的变量

现在,我可以将f1f2的环境覆盖到baseenv()new.env(parent=environment(2L))

environment(f1) = baseenv()
environment(f2) = baseenv()
f1(3)    # fails, as it should
f2(iris) # fails, because %>% is not in function env

或:

# detaching here makes `dplyr` inaccessible for `f2`
# not detaching leaves `head` inaccessible for `f2`
detach("package:dplyr", unload=TRUE)
environment(f1) = new.env(parent=as.environment(2L))
environment(f2) = new.env(parent=as.environment(2L))
f1(3)    # fails, as it should
f2(iris) # fails, because %>% is not in function env

有没有办法覆盖函数的环境,使其必须自给自足,但只要它加载自己的库,它也总能工作?

1 个答案:

答案 0 :(得分:3)

问题在于,从根本上说,library和类似的工具不提供作用域,并且不能用于范围: 1 即使{{1在函数内部执行,其效果实际上是全局的,而不是本地的。 呃。

具体而言,您将功能与全球环境隔离的方法是合理的;但是,library操纵library路径(通过search),并且函数的环境未被“通知”:它仍将指向 previous 第二个搜索路径条目作为其祖父母。

attach / library / ...被调用时,您需要找到更新功能环境的祖父母环境的方法。您可以通过将函数的父环境中的attach替换为您自己的调用library修改版本的版本来实现此目的。这个attach不仅可以调用原始attach2,还可以重新链接您环境的父级。

1 除此之外,‹modules›解决了所有这些问题。在代码中用attach替换library(foo)可以使其正常工作。这是因为模块具有强大的范围和环境感知能力。