强制 R 函数调用自给自足
Force R function call to be self-sufficient
我正在寻找一种方法来调用不受 .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
有没有办法覆盖函数的环境,使其必须自给自足,但只要它加载自己的库,它也总是有效?
这里的问题是,从根本上说,library
和类似的工具不提供作用域,也不是为了与作用域一起工作而设计的:1尽管 library
是在函数内部执行的,但它的作用实际上是全局的,而不是局部的。 呃
具体来说,您将函数与全局环境隔离的方法是合理的;然而,library
操纵 search
路径(通过 attach
),并且函数的环境不会“通知”这一点:它仍然指向 previous 第二个搜索路径条目作为其总parent.
当 library
/attach
/... 被调用时,您需要找到一种方法 更新 函数环境的 grandparent 环境。您可以通过将函数的 parent 环境中的 library
等替换为您自己调用 attach
的修改版本的版本来实现此目的。这个 attach2
不仅会调用原来的 attach
,还会重新链接您环境的 parent。
1 顺便说一句,“box”解决了所有这些问题。在您的代码中将 library(foo)
替换为 box::use(foo[...])
即可使其正常工作。这是因为模块的范围很广,environment-aware.
我正在寻找一种方法来调用不受 .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
有没有办法覆盖函数的环境,使其必须自给自足,但只要它加载自己的库,它也总是有效?
这里的问题是,从根本上说,library
和类似的工具不提供作用域,也不是为了与作用域一起工作而设计的:1尽管 library
是在函数内部执行的,但它的作用实际上是全局的,而不是局部的。 呃
具体来说,您将函数与全局环境隔离的方法是合理的;然而,library
操纵 search
路径(通过 attach
),并且函数的环境不会“通知”这一点:它仍然指向 previous 第二个搜索路径条目作为其总parent.
当 library
/attach
/... 被调用时,您需要找到一种方法 更新 函数环境的 grandparent 环境。您可以通过将函数的 parent 环境中的 library
等替换为您自己调用 attach
的修改版本的版本来实现此目的。这个 attach2
不仅会调用原来的 attach
,还会重新链接您环境的 parent。
1 顺便说一句,“box”解决了所有这些问题。在您的代码中将 library(foo)
替换为 box::use(foo[...])
即可使其正常工作。这是因为模块的范围很广,environment-aware.