Получение имени объекта для метода печати S3 не удается

Определите объект класса S3 «bar» и метод печати:

foo=list(1)
class(foo) <- c("bar")
print.bar <- function(x,...){
  cat("print.bar says this was ",deparse(substitute(x)),"\n")
}

Теперь print (foo) делает следующее:

> print(foo)
print.bar says this was  foo 

Отлично, но автоматическая печать не работает:

> foo
print.bar says this was  structure(list(1), class = "bar")

Я предполагаю, что это как-то связано с тем, как строка оценивается как выражение верхнего уровня. Быстрый поиск на R-devel безрезультатно. Кто-нибудь знает, как это исправить?

Причина, по которой мне нужно это имя, заключается в том, что то, что я определяю, является функцией, и я хочу иметь возможность поместить «try foo (2)» в метод печати (получая «foo» из имени объекта). Да, вы можете создавать подклассы функций в S3. Полагаю, могут быть и другие пифоллы ..


person Spacedman    schedule 10.02.2011    source источник


Ответы (2)


Это довольно особый случай, поскольку R заменяет foo своим значением перед вызовом print, когда вы вводите имя в командной строке. Это можно проиллюстрировать:

foo=list(1)
class(foo) <- c("bar")
print.bar <- function(x,...){
  print(sys.calls())
}

> foo
[[1]]
print(list(1))

[[2]]
print.bar(list(1))

> print(foo)
[[1]]
print(foo)

[[2]]
print.bar(foo)

Таким образом, без имени в качестве атрибута (как показал Аарон) невозможно извлечь имя объекта из любого места. Его просто нет в стеке вызовов.

person Joris Meys    schedule 10.02.2011
comment
Да, похоже, это невозможно. Я мог бы взглянуть на источник, чтобы увидеть, как именно это происходит. Спасибо! - person Spacedman; 11.02.2011

Если вы не собираетесь переименовывать объект, вы можете включить имя в качестве атрибута и вместо этого распечатать его.

foo <- structure(list(1), class="bar", name="foo")
print.bar <- function(x,...){
  cat("print.bar says this was",attr(x, "name"),"\n")
}

Тогда он сделает то, что вы ожидаете:

> print(foo)
print.bar says this was foo 
> foo
print.bar says this was foo 

Если вы не используете другое имя для одного и того же объекта:

> fooX <- foo
> fooX
print.bar says this was foo 
person Aaron left Stack Overflow    schedule 10.02.2011