Хотя, похоже, есть различия в возврате списка и окружающей среды.От Advanced R :
Обычно среда похожа на список с четырьмя важными исключениями:
Каждое имя всреда уникальна.
Имена в среде не упорядочены (т. е. не имеет смысла спрашивать, что является первым элементом среды).
У среды есть родительский элемент.
В средах есть эталонная семантика.
Более технически среда составленаиз двух компонентов: фрейм, который содержит привязки объекта имени (и ведет себя так же, как именованный список), и родительская среда.К сожалению, «frame» используется в 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