parent.env (x) путаница - PullRequest
       15

parent.env (x) путаница

10 голосов
/ 26 декабря 2011

Я прочитал документацию для parent.env (), и она кажется довольно простой - она ​​возвращает окружающую среду.Однако, если я использую parent.env () для обхода цепочек окружающих сред, я вижу то, что не могу объяснить.Сначала код (взят из «R в двух словах»)

library( PerformanceAnalytics )
x = environment(chart.RelativePerformance)
while (environmentName(x) != environmentName(emptyenv())) 
{ 
    print(environmentName(parent.env(x)))
    x <- parent.env(x)
}

И результаты:

[1] "imports:PerformanceAnalytics"
[1] "base"
[1] "R_GlobalEnv"
[1] "package:PerformanceAnalytics"
[1] "package:xts"
[1] "package:zoo"
[1] "tools:rstudio"
[1] "package:stats"
[1] "package:graphics"
[1] "package:utils"
[1] "package:datasets"
[1] "package:grDevices"
[1] "package:roxygen2"
[1] "package:digest"
[1] "package:methods"
[1] "Autoloads"
[1] "base"
[1] "R_EmptyEnv"

Как мы можем объяснить «основание» сверху и «база "внизу?Кроме того, как мы можем объяснить «пакет: PerformanceAnalytics» и «импорт: PerformanceAnalytics»?Все казалось бы последовательным без первых двух строк.То есть функция chart.RelativePerformance находится в пакете: среда PerformanceAnalytics, которая создается xts, которая создается zoo, ... вплоть до (или вниз) до базовой и пустой среды.

Кроме того, документация не очень ясна по этому вопросу - является ли "окружающая среда" средой, в которой создается другая среда, и, таким образом, parent.env () показывает цепочку "создания"?

Править

Бесстыдный плагин: я написал сообщение в блоге , которое объясняет окружения, parent.env (), вложения, пространство имен / пакет и т. Д. С помощью интуитивных диаграмм.

Ответы [ 3 ]

5 голосов
/ 26 декабря 2011

1) Относительно того, как base может быть там дважды (учитывая, что окружения образуют дерево), это ошибка функции environmentName.На самом деле первое вхождение - .BaseNamespaceEnv, а второе - baseenv().

> identical(baseenv(), .BaseNamespaceEnv)
[1] FALSE

2) Относительно imports:PerformanceAnalytics - особой среды, которую R устанавливает для хранения импорта, упомянутого вФайл NAMESPACE или DESCRIPTION, чтобы объекты в нем встречались раньше всего.

Попробуйте выполнить это для большей ясности.str(p) и следующие if операторы дадут лучшее представление о том, что такое p:

library( PerformanceAnalytics )
x <- environment(chart.RelativePerformance)
str(x)
while (environmentName(x) != environmentName(emptyenv())) { 
    p <- parent.env(x)
    cat("------------------------------\n")
    str(p)
    if (identical(p, .BaseNamespaceEnv)) cat("Same as .BaseNamespaceEnv\n")
    if (identical(p, baseenv())) cat("Same as baseenv()\n")
    x <- p
}
3 голосов
/ 26 декабря 2011

Вторая base равна .BaseNamespaceEnv, а вторая до последней base равна baseenv().Они ничем не отличаются (вероятно, от его родителей).Родитель .BaseNamespaceEnv равен .GlobalEnv, а родитель baseenv() равен emptyenv().

В пакете, как говорит @Josh, R ищет пространство имен пакета, затем импортирует изатем основание (т. е. BaseNamespaceEnv).

Вы можете найти это, например:

> library(zoo)

> packageDescription("zoo")
Package: zoo

# ... snip ...

Imports: stats, utils, graphics, grDevices, lattice (>= 0.18-1)

# ... snip ...

> x <- environment(zoo)

> x
<environment: namespace:zoo>

> ls(x) # objects in zoo
  [1] "-.yearmon"                "-.yearqtr"                "[.yearmon"               
  [4] "[.yearqtr"                "[.zoo"                    "[<-.zoo"                 
# ... snip ...

> y <- parent.env(x)
> y # namespace of imported packages
<environment: 0x116e37468>
attr(,"name")
[1] "imports:zoo"

> ls(y) # objects in the imported packages

   [1] "?"                                     "abline"                               
   [3] "acf"                                   "acf2AR"                               
# ... snip ...
3 голосов
/ 26 декабря 2011

Первые несколько элементов в ваших результатах свидетельствуют о правилах, которые R использует для поиска переменных, используемых в функциях в пакетах с пространствами имен.Из руководства R-ext :

Пространство имен управляет стратегией поиска переменных, используемых функциями в пакете.Если не найдено локально, R сначала ищет пространство имен пакета, затем импортирует, затем базовое пространство имен и затем обычный путь поиска.

Немного проработав, взглянем на первые несколько строк:chart.RelativePerformance:

head(body(chart.RelativePerformance), 5)
# {
#     Ra = checkData(Ra)
#     Rb = checkData(Rb)
#     columns.a = ncol(Ra)
#     columns.b = ncol(Rb)
# }

При оценке вызова на chart.RelativePerformance каждый из этих символов --- будь то checkData в строке 1 или ncol в строке 3 -- нужно найти где-то на пути поиска.Вот первые несколько проверенных окружающих сред:

  • Сначала namespace:PerformanceAnalytics.checkData найден там, но ncol нет.

  • Следующая остановка (и первое место, указанное в ваших результатах) - imports:PerformanceAnalytics.Это список функций, указанных как импорт в файле пакета NAMESPACE.ncol здесь также не найден.

  • Пространство имен среды base (где будет найдено ncol) - это последняя остановка перед переходом к обычному пути поиска.Почти любая функция R будет использовать некоторые функции base, поэтому эта остановка гарантирует, что ни одна из этих функций не будет нарушена объектами в глобальной среде или в других пакетах.(Дизайнеры R могли бы оставить авторам пакета возможность явно импортировать среду base в свои файлы NAMESPACE, но добавление этого прохода по умолчанию через base кажется лучшим решением для проектирования.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...