5

在以下两种情况下,使用其中一种有什么优势/劣势?Case-I 将其输出作为环境返回,Case-II 将其输出作为列表返回。

案例一:

function(x) {
  ret <- new.env()
  ret$x <- x
  ret$y <- x^2
  return(ret)
}

案例二:

function(x) {
  ret <- list()
  ret$x <- x
  ret$y <- x^2
  return(ret)
}
4

1 回答 1

6

尽管相似,但返回列表和环境存在差异。从高级 R

通常,环境类似于列表,但有四个重要例外:

  • 环境中的每个名称都是唯一的。

  • 环境中的名称没有顺序(即,询问环境的第一个元素是什么是没有意义的)。

  • 一个环境有一个父级。

  • 环境具有引用语义。

从技术上讲,环境由两个组件组成,框架包含名称-对象绑定(并且行为很像命名列表),以及父环境。不幸的是,“框架”在 R 中的使用不一致。例如,parent.frame() 不会为您提供环境的父框架。相反,它为您提供调用环境。这在调用环境中有更详细的讨论。

从帮助:

help(new.env)

环境由一个框架或命名对象的集合和一个指向封闭环境的指针组成。最常见的例子是函数调用的局部变量框架;它的外壳是定义函数的环境(除非随后更改)。封闭环境与父框架不同:后者(由 parent.frame 返回)指的是函数调用者的环境。因为很容易混淆,所以最好不要在环境中使用“parent”(尽管存在 parent.env 函数)。

从函数的文档中:

e1 <- new.env(parent = baseenv())  # this one has enclosure package:base.
e2 <- new.env(parent = e1)
assign("a", 3, envir = e1)
ls(e1)
#[1] "a"

但是ls会给出创建的环境:

ls()
#[1] "e1" "e2"

您可以像列表一样访问您的环境对象:

e1$a
#[1] 3

玩弄你的功能:

f1 <- function(x) {
   ret <- new.env()
   ret$x <- x
   ret$y <- x^2
   return(ret)
}

res <- f1(2)
res
#<environment: 0x0000021d55a8a3e8>

res$y
#[1] 4

f2 <- function(x) {
   ret <- list()
   ret$x <- x
   ret$y <- x^2
   return(ret)

res2 <- f(2)
res2
#$x
#[1] 2

#$y
#[1] 4

res2$y
#[1] 4

他们的表现非常相似,根据microbenchmarking

microbenchmark::microbenchmark(
   function(x) {
      ret <- new.env()
      ret$x <- x
      ret$y <- x^2
      return(ret)
   },
   function(x) {
      ret <- list()
      ret$x <- x
      ret$y <- x^2
      return(ret)
   },
   times = 500L
)

#Unit: nanoseconds
#                                                                                 #expr
# function(x) {     ret <- new.env()     ret$x <- x     ret$y <- x^2     #return(ret) }
#    function(x) {     ret <- list()     ret$x <- x     ret$y <- x^2     #return(ret) }
# min lq   mean median  uq  max neval
#   0  1 31.802      1 100  801   500
#   0  1 37.802      1 100 2902   500

他们返回相同大小的对象:

object.size(res)
#464 bytes

object.size(res2)
#464 bytes

并且您始终可以从环境 ( list2env) 和逆 ( as.list) 生成列表:

L <- list(a = 1, b = 2:4, p = pi, ff = gl(3, 4, labels = LETTERS[1:3]))
e <- list2env(L)
e$ff
# [1] A A A A B B B B C C C C
#Levels: A B C

as.list(e)
#$ff
# [1] A A A A B B B B C C C C
#Levels: A B C
#
#$p
#[1] 3.141593
#
#$b
#[1] 2 3 4
#
#$a
#[1] 1
于 2019-02-05T15:20:03.173 回答