【问题标题】:In what cases should new.env be used to create a new environment?在什么情况下应该使用 new.env 来创建新环境?
【发布时间】:2011-03-17 02:38:50
【问题描述】:

在“什么是最有用的 R 技巧?” (here),我读到使用环境提供了“通过引用的能力”。这种方法是否有任何限制和/或陷阱?

另外,总的来说,使用创建的环境有哪些优点和缺点?这是我很长一段时间以来一直感到困惑的事情,因此任何澄清或参考对我都会非常有帮助。

提前谢谢你。

【问题讨论】:

  • 这可能很棘手,而且肯定超出了“标准”R 用户所需的范围(install.packages + 导入数据 + 在data.frames 上运行统计测试)。但是对于繁琐的任务,我有时会想到 new.env 就像创建一个指针。如果我想模拟 C struct,那么我会使用一系列嵌套的 new.env's。
  • 你也可以在环境中使用multi-assign。 (一个据称缺失的功能,例如 Pythonistas 有时会抱怨。)

标签: r


【解决方案1】:

好吧,如果您不了解它们,并且您可能有一天不得不阅读您的代码的人(包括您未来的自己)不了解环境,那么您不应该使用它们!它们旨在用于将名称空间封装在包等中。您可以将它们用于传递引用和哈希表这一事实并不一定意味着您应该。这是一个把戏。一般来说,使用deep magic 并不可取,即使它会使您的代码更快一点。

【讨论】:

  • 所以每当我遇到一个新技巧时,我应该避免它,因为我不明白它?我经常通过在函数之间传递大型协方差矩阵来执行操作。在这种情况下,使用环境会提高性能,足以保证使用它们吗?
  • 我不完全确定实现细节,但我相信如果你不修改函数中的大矩阵,它们实际上并没有被复制。至于你更大的问题,我建议如果你需要速度,可能值得学习魔法,只要记住这样做是对语言语义的(轻度)滥用,你可能会后悔之后。或者,您可能不会后悔!
  • +1 谈谈 Harlan 的担忧:是的,这是一个危险的用法,因为它引入了“副作用”。每当你允许一个函数改变外部世界时,你就是在向意想不到的行为敞开大门。 en.wikipedia.org/wiki/Side_effect_(computer_science)
  • +1 对 Shane 的评论。在这个日益并行化的世界中,开始减少副作用的使用是一种很好的做法。
【解决方案2】:

虽然我同意 Harlan 的总体建议(即除非您理解,否则不要使用某些东西),但我会补充:

环境是 R 中的一个基本概念,在我看来,它非常有用(换句话说:它们值得理解!)。环境对于理解与范围相关的问题非常重要。在这种情况下您应该了解的一些基本知识:

  1. search():将向您展示工作区;环境按优先级顺序列出。主环境是 .GlobalEnv,始终可以这样引用。
  2. ls(): 将向您展示环境中包含的内容
  3. attach/detach:为对象创建新环境
  4. getassign<<-<-:你应该知道这些函数的区别
  5. with:一种在不附加环境的情况下使用环境的方法。

另一个指针:看看the proto package(用于ggplot),它使用环境来提供受控继承。

最后,我要指出环境与列表非常相似:它们都可以在其中存储任何类型的对象(请参阅this question)。但是根据您的用例(例如,您是否想处理继承和优先级),列表可能更容易使用。而且你总是可以attach一个列表作为环境。

编辑:如果你想在ggplot 中查看proto 的示例,请查看 ggplot 对象的结构,它本质上是一个由部分环境组成的列表:

> p <- qplot(1:10, 1:10)
> str(p)
List of 8
 $ data       :'data.frame':    0 obs. of  0 variables
 $ layers     :List of 1
  ..$ :proto object 
 .. .. $ legend     : logi NA 
 .. .. $ inherit.aes: logi TRUE 
...
> class(p$layers[[1]])
[1] "proto"       "environment"
> is.environment(p$layers[[1]])
[1] TRUE

请注意它是如何使用 proto 构建的,因此包含许多环境。您还可以使用graph.proto 绘制这些对象中的关系。

【讨论】:

  • 我希望了解它们,以便我可以潜在地使用它们。我对 R 中的范围规则以及您列出的大多数函数有些熟悉,但我将更深入地探讨其中的细节。感谢您的信息。
  • 完全同意,Shane!如果您要构建大量代码,了解 R 中的环境和范围很重要!但这并不一定意味着您应该将环境用作数据结构。
  • @Harlan:我完全同意。也许我应该在这方面更有力。 @John:除非您(1)理解它们并且(2)有充分的理由这样做,否则不要使用环境。列表通常是更好的选择。 IMO,除非绝对不能,否则最好避免副作用!
  • 感谢 Shane 的回答,我注意到它没有被接受,所以我认为这意味着我可以如此大胆地要求更多?我有一个数据集保存在一个新环境中,例如名为dta.env,所以我做了 ls(dta.env),但它只返回了一个数据代码列表。有没有办法更深入地探索环境?更详尽地了解里面的内容? (不确定这是否完全是一个新问题)如果 ls() 有更多内容,请您扩展一下吗?无论如何,谢谢。
  • 要了解环境,您还需要知道every environment has a parent environment,并且通过对环境的一些操作(例如,exists)会找到来自父作用域的名称。要创建一个没有父母的环境 give it the empty environment: new.env(parent = emptyenv())
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多