Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In R, how can I print the name of an object reliably from a custom print function?

I created a class in R, and am trying to create a print function for that class. I'd like the print function to print the name of the object being passed to the print function. Using the standard deparse(substitute()) I can get the name of the variable, and this works when I call the print() function directly. But it doesn't work when I just run the variable from R Studio. It is obviously calling my print function. But there is some indirection that is causing it to lose the variable name. Here is an example:

# Define class 'myobj'
myobj <- function(val) {
  
  obj <- structure(list(), class = c("myobj", "list")) 
  
  obj$value = val
  
  return(obj)
}

# Write custom print function for 'myobj' class
#' @export
print.myobj <- function(x, ...) {
  
  nm <- deparse1(substitute(x, env = environment()))
  cat(paste0("My object name: ", nm, "\n"))
  cat(paste0("My object value: ", x$value, "\n"))
      
  invisible(x)
}

myInstance <- myobj(123)

# Prints name and value.  
print(myInstance)

#> My object name: myInstance
#> My object value: 123

# Prints value, but name is local variable 'x'. 
myInstance

#> My object name: x
#> My object value: 123

It seems like when you run the variable directly, it is getting nested in another frame or environment, such that the deparse(substitute()) isn't working.

How can I get my print function to print the name of the variable reliably, no matter how it is called?

like image 698
David J. Bosak Avatar asked Oct 03 '20 23:10

David J. Bosak


People also ask

How do I print names in R?

Print Function in R – Cat Function in R Simply enter the variable name or expression at the command prompt, R will print its value. Use the print function for generic printing of any object.

How do I print the value of an object in R?

identity() function in R Language is used to print the value of the object which is passed to it as argument.

How do I print text code in R?

To display ( or print) a text with R, use either the R-command cat() or print(). Note that in each case, the text is considered by R as a script, so it should be in quotes. Note there is subtle difference between the two commands so type on your prompt help(cat) and help(print) to see the difference.

How do I print a specific value in R?

To print the data on the console in R, use the print () function. The print () is a built-in R function that prints its argument. The print () function accepts three arguments and does not return any value. Instead, the print () method will print out the argument on the screen.

How to print the data on the console in R?

Every language provides some functions that can help you print the data on the console, and R is no different. To print the data on the console in R, use the print () function. The print () is a built-in R function that prints its argument. The print () function accepts three arguments and does not return any value.

What is print and Cat in R?

The article consists of three examples for the application of print and cat. To be more specific, the content is structured as follows: Definitions: Please find the definitions of the print & cat functions below. The print R function returns a data object to the R (or RStudio) console.

Can the print function be used to return a data object?

As you have seen in Example 2, the print function must not be used to return a data object to the console. However, the print function provides additional arguments that can be specified within the print function. In this Example, I’ll show how to modify the console output when printing numeric values. First, let’s create a numeric data object:


1 Answers

The autoprinting documentation says it is handled by print.c.

This function looks like this.

static void PrintObjectS3(SEXP s, R_PrintData *data)
{
    /*
      Bind value to a variable in a local environment, similar to
      a local({ x <- <value>; print(x) }) call. This avoids
      problems in previous approaches with value duplication and
      evaluating the value, which might be a call object.
    */
    SEXP xsym = install("x");
    SEXP mask = PROTECT(NewEnvironment(R_NilValue, R_NilValue, data->env));
    defineVar(xsym, s, mask);

    /* Forward user-supplied arguments to print() */
    SEXP fun = PROTECT(findFun(install("print"), R_BaseNamespace));
    SEXP args = PROTECT(cons(xsym, data->callArgs));
    SEXP call = PROTECT(lcons(fun, args));

    eval(call, mask);

    defineVar(xsym, R_NilValue, mask); /* To eliminate reference to s */
    UNPROTECT(4); /* mask, fun, args, call */
}

Note that it says

similar to a local({ x <- <value>; print(x) })

So autoprinting does not directly call print(myInstance). It does things with the symbol x so I think getting the variable name in the way you want is not possible.

The difference can be seen by looking at the traceback.

print.myobj <- function(x, ...) {
  stop()
}

print(myInstance)
#> (Traceback)
#> 3. stop() 
#> 2. print.myobj(myInstance) 
#> 1. print(myInstance) 

myInstance
#> (Traceback)
#> 3. stop() 
#> 2. print.myobj(x) 
#> 1. (function (x, ...) 
#>    UseMethod("print"))(x)
like image 182
Paul Avatar answered Oct 10 '22 10:10

Paul