r - 强制 R 函数调用自给自足

标签 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 =环境(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),并且函数的环境不会“通知”这一点:它仍然会指向将第二个搜索路径条目作为其祖 parent 。

您需要找到一种方法,在调用 library/attach/… 时更新函数环境的祖父环境。您可以通过将函数父环境中的 library 等替换为您自己的调用 attach 修改版本的版本来实现此目的。此attach2不仅会调用原始attach,还会重新链接您的环境的父环境。


1 顺便说一句,‘box ’解决了所有这些问题。在代码中将 library(foo) 替换为 box::use(foo[...]) 即可使其正常工作。这是因为模块具有很强的作用域和环境感知能力。

关于r - 强制 R 函数调用自给自足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45889756/

相关文章:

r - deSolve:无法理解如何使用根函数提前停止 ode 求解器

javascript - R Shiny-为电缆表添加额外的标题行 'sticky'

r - 使用dplyr将变量作为函数的默认参数

apache - .htaccess 在多个环境中

php - Symfony 环境和调试栏

r - 如何将 2 个字符向量的组合识别为预定义向量的名称

r - 从数据框列中获取最频繁的字符串

ruby-on-rails - 属性在belongs_to 对象中的范围

Node.js 中的 JavaScript 作用域

java - Spring PropertyPlaceholderConfigurer 可以忽略属性位置路径中未设置的属性吗?