我正在寻找一种方法来调用不受.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)
应该通过,因为该函数不引用其范围之外的变量现在,我可以将f1
和f2
的环境覆盖到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
有没有办法覆盖函数的环境,使其必须自给自足,但只要它加载自己的库,它也总能工作?
答案 0 :(得分:3)
问题在于,从根本上说,library
和类似的工具不提供作用域,并且不能用于范围: 1 即使{{1在函数内部执行,其效果实际上是全局的,而不是本地的。 呃。
具体而言,您将功能与全球环境隔离的方法是合理的;但是,library
操纵library
路径(通过search
),并且函数的环境未被“通知”:它仍将指向 previous 第二个搜索路径条目作为其祖父母。
当attach
/ library
/ ...被调用时,您需要找到更新功能环境的祖父母环境的方法。您可以通过将函数的父环境中的attach
替换为您自己的调用library
修改版本的版本来实现此目的。这个attach
不仅可以调用原始attach2
,还可以重新链接您环境的父级。
1 除此之外,‹modules›解决了所有这些问题。在代码中用attach
替换library(foo)
可以使其正常工作。这是因为模块具有强大的范围和环境感知能力。