Равенство значений / ссылок для одноименных функций в средах пакетов / пространств имен? - PullRequest
11 голосов
/ 14 февраля 2012

Давайте возьмем окружения "пространство имен: статистика" и "пакет: статистика"

ns = getNamespace( "stats" )
pkg = as.environment( "package:stats" )

Теперь давайте получим функцию "sd" в обоих:

nsSd = get( "sd" , envir = ns , inherits = FALSE )
pkgSd = get( "sd" , envir = pkg , inherits = FALSE )

Являются ли онитак же?Они есть!Но что значит "то же самое"?Ссылка или равенство значений?

identical( nsSd , pkgSd )

Это подразумевает равенство ссылок, поскольку следующее возвращает FALSE:

test1 = function() {}
test2 = function() {}
identical( test1 , test2 )

Но если это так, это означает, что фрейм окружения может содержать указатели на функции нарядуфункциональные объекты.Еще более усложняет проблему тот факт, что функция может «жить» в одной среде, но функции можно сказать, что ее исполняющая среда - это другая среда.Камеры SoDA, кажется, не имеет ответа (это плотная книга, может быть, я пропустил это!)

Итак, я хотел бы получить окончательный ответ.Какие из следующих являются правильными?Или здесь есть ложная трихотомия?

  1. nsSd и pkgSd - два разных объекта (хотя и копии друг друга), где объект в pkgSd имеет ns в качестве исполняющегоenvironment
  2. nsSd и pkgSd являются указателями на один и тот же объект.
  3. nsSd - указатель на pkgSd, и поэтому они рассматриваются как идентичные

Ответы [ 2 ]

5 голосов
/ 16 февраля 2012

Они являются указателями на один и тот же объект.Используя этот ответ на другой вопрос , мы можем проверить, относятся ли два объекта к одному и тому же месту в памяти.

are_same <- function(x, y)
{
  f <- function(x) capture.output(.Internal(inspect(x)))
  all(f(x) == f(y))
}

are_same(nsSd, pkgSd) #TRUE
are_same(1:5, 1:5)    #FALSE
4 голосов
/ 14 февраля 2012

Это в основном не ответ на ваш главный вопрос. В этом вопросе, однако, я согласен с Дирком: есть только одна функция sd(), и к ней можно получить доступ, в зависимости от обстоятельств, разными путями видимости Например, когда вы набираете sd(x) в командной строке, функция, соответствующая имени sd, будет найдена через ее запись в кадре среды package:stats. Когда вы набираете stats:::sd(x) или когда другая функция в пакете stats вызывает sd(x), она будет найдена с помощью поиска в среде namespace:stats.


Вместо этого я просто хотел подчеркнуть, что ваш пример, использующий test1() и test2(), на самом деле ничего не подразумевает в «равенстве ссылок» объектов, которые оцениваются как identical. Чтобы увидеть истинную причину, по которой эти двое не identical, взгляните на их структуру, показанную str():

test1 <- function() {}
test2 <- function() {}
identical( test1 , test2 )
# [1] FALSE

str(test1)
# function ()  
#  - attr(*, "srcref")=Class 'srcref'  atomic [1:8] 1 13 1 25 13 25 1 1
#   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x01613f54> 

str(test2)
# function ()  
#  - attr(*, "srcref")=Class 'srcref'  atomic [1:8] 1 13 1 25 13 25 1 1
#   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x01615730> 

Если вы перейдете к правой стороне поля кода выше, вы увидите, что две функции отличаются по одному из своих атрибутов, а именно, среде, связанной с их исходными файлами. (Я не знаю много об этом атрибуте, но это не очень важно здесь. Дело в том, что они не identical!)

Если вы скажете R, что не хотите хранить данные атрибутов исходного файла для каждой созданной функции, «неожиданное» поведение identical(test1, test2) исчезнет:

options(keep.source=FALSE)
test1 <- function() {}
test2 <- function() {}
identical( test1 , test2 )
# [1] TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...