It is easier to explain what's going on than it is to fix it. If we start by looking at the generic print
we can see it simply dispatches the class-appropriate print
method via UseMethod("print")
:
print
#> function (x, ...)
#> UseMethod("print")
So when you call print(obj)
, you are calling the generic function print(obj)
first, which then calls print.new_obj(obj)
. We can confirm this by adding print(sys.calls())
to your print method:
print.new_obj <- function(y){
print(sys.calls())
cat("New object name:\n")
cat(deparse(substitute(y)))
}
print(obj)
#> [[1]]
#> print(obj)
#>
#> [[2]]
#> print.new_obj(obj)
#>
#> New object name:
#> obj
So far, so good, and I suspect you already knew all this.
What happens now, when you just type obj
into the console?
obj
#> [[1]]
#> (function (x, ...)
#> UseMethod("print"))(x)
#>
#> [[2]]
#> print.new_obj(x)
#>
#> New object name:
#> x
Now we can see where the x
comes from. It is taken from a behind-the-scenes call to the generic print
which is actually called as an unnamed function. Hence the name of the variable is not actually included in the call stack. There are other questions on SO where it says this makes the problem insoluble. This isn't true; it just means you will need to look outside of the call stack for your object:
print.new_obj <- function(y){
obj_name <- deparse(substitute(x, parent.frame()))
if (obj_name != "x")
{
obj_name <- names(which(sapply(ls(envir = parent.frame(2)), function(v)
identical(y, get(v, envir = parent.frame(2))))))[1]
cat("New object name:\n", obj_name)
}
else cat("New object name:\n", deparse(substitute(y)))
}
print(obj)
#> New object name:
#> obj
obj
#> New object name:
#> obj
Of course, you wouldn't want to use this in production code, for all sorts of reasons. It is not particularly useful or logical for a data structure to know what name it has been assigned in a particular environment, and would not be an idiomatic way to write a package for other users.
Still, nice to know it is possible.