I have encountered two instances where it seems that R treats obj
and print(obj)
differently. I would like to know more about the nature of this difference.
I can run
trace("print.default", where = print)
to trace the default print function.
And indeed, this seems to work as expected:
> print("Hello world!")
Tracing print.default("Hello world!") on entry
[1] "Hello world!"
However, this does not work if I rely on the auto-print behavior:
> "Hello world!"
[1] "Hello world!"
Why is the tracing code not run for auto-printed objects in R? How can I change that?
I can define a print method for NULL
objects:
.S3method("print", "NULL", function(x, ...) cat("NULL object\n"))
Again, this works when calling print()
explicitly:
> print(NULL)
NULL object
But not when relying on auto-printing:
> NULL
NULL
Why does R not dispatch to my custom print function? How can I make it work?
The instances 1 and 2 defy my expectations in a similar way, so I assume there may be a common cause. What is it?
As Nir Graham suggested in the answer on a similar question, R Internals is enlightening in this regard, in particular the section on autoprinting:
The actual autoprinting is done by
PrintValueEnv
in fileprint.c
. If the object to be printed has the S4 bit set and S4 methods dispatch is on,show
is called to print the object. Otherwise, if the object bit is set (so the object has a"class"
attribute),print.default
is called.
In other words, as "Hello world!"
and NULL
have no class
attribute set, print()
is never called. Indeed, adding the class
attribute resolves the situation for the first instance:
> structure("Hello world!", class = "any_class")
Tracing print.default(x) on entry
[1] "Hello world!"
attr(,"class")
[1] "any_class"
For the second instance, as NULL
cannot have attributes, this can be demonstrated with numerics instead:
> .S3method("print", "numeric", function(x, ...) cat("numeric object\n"))
> print(3)
numeric object
> 3
[1] 3
> structure(3, class = "numeric")
numeric object
print.c
puts it succinctly:
/*
* auto-printing -> PrintValueEnv
* -> PrintValueRec
* -> call print() for objects
* Note that auto-printing does not call print.default.
* PrintValue, R_PV are similar to auto-printing.
*/
Consequently, there should be no way to change the way objects without a class are auto-printed at the top-level.