Значение/ссылочное равенство для той же именованной функции в среде пакета/пространства имен?
Позволяет захватить среды "пространство имен: статистика" и "пакет: статистика"
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 )
Но если это правда, это означает, что кадр среды может содержать указатели на функции вместе с объектами функции. Дальнейшее усложнение проблемы - факт, что функция может "жить" в одной среде, но функции можно сказать, что ее исполняющая среда является другой средой. Chambers SoDA, похоже, не имеет ответа (его плотная книга, может быть, я пропустил это!)
Итак, я бы хотел дать окончательный ответ. Что из следующего верно? Или здесь есть ложная трихотомия?
-
nsSd
и pkgSd
- это два разных объекта (хотя копии каждого
другое), где объект в pkgSd
имеет ns
в качестве его выполнения
окружающая среда
-
nsSd
и pkgSd
являются указателями на один и тот же объект.
-
nsSd
является указателем на pkgSd
и как таковой они рассматриваются как идентичные
Ответы
Ответ 1
Они являются указателями на один и тот же объект. Используя этот ответ на другой вопрос, мы можем проверить, ссылаются ли два объекта на одно и то же место в памяти.
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
Ответ 2
Это не является главным ответом на ваш основной вопрос. Однако по этому вопросу я согласен с Dirk: существует только одна функция 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