Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print methods and the environment pane for R6 instances #217

Closed
mattwarkentin opened this issue Oct 21, 2020 · 8 comments
Closed

Print methods and the environment pane for R6 instances #217

mattwarkentin opened this issue Oct 21, 2020 · 8 comments

Comments

@mattwarkentin
Copy link

Hi @wch,

I just have a couple (probably) simple questions about the R6 print method and also how to modify how an R6 object is displayed in the Environment pane in RStudio.

For the first part, if I didn't feel like designing a whole custom print method for my R6 class, is there a way to modify how a public method or field is presented?

I see that print.R6 is:

function (x, ...) 
{
    if (is.function(.subset2(x, "print"))) {
        .subset2(x, "print")(...)
    }
    else {
        cat(format(x, ...), sep = "\n")
    }
    invisible(x)
}

So for example, the default way an array is presented is:

library(R6)

R6Class(
  "foo",
  public = list(
    aaa = array(runif(1000), dim = c(10, 10, 10))
  )
)$new()
#> <foo>
#>   Public:
#>     aaa: 0.304002771619707 0.662762265419587 0.892216055653989 0. ...
#>     clone: function (deep = FALSE) 

But I would like to customize it to show the dimensions, so I thought a new S3 method for format would work, but it doesn't. Moving format.array to the global environment didn't help either.

library(R6)

R6Class(
  "foo",
  public = list(
    aaa = array(runif(1000), dim = c(10, 10, 10)),
    format.array = function(x, ...) {
      "[10 x 10 x 10]"
    }
  )
)$new()
#> <foo>
#>   Public:
#>     aaa: 0.887192418565974 0.142298782011494 0.786215221509337 0. ...
#>     clone: function (deep = FALSE) 
#>     format.array: function (x, ...)

Can this be achieved without defining a custom print method (such as by writing a new S3 method for format)?


Second, it's my understanding that RStudio uses str() S3 methods to present objects in the Environment pane. But no matter what I've tried I can't seem to get my R6 object to show up differently in the pane. Is this possible? If so, any suggestions on how to achieve this?

@gaborcsardi
Copy link
Member

This is how to create a print method: https://r6.r-lib.org/articles/Introduction.html#printing-r6-objects-to-the-screen

For str you can create an "external" method I believe, i.e.

str.foo <- function(object, ...) {
  ...
}

@mattwarkentin
Copy link
Author

I figured I would be able to avoid creating a print method if I wrote format methods. Shouldn't that work since format is what is called by print.R6?

@gaborcsardi
Copy link
Member

gaborcsardi commented Oct 21, 2020

That works as well:

foo <- R6::R6Class("foo",
  public = list(
    format = function(...) "foobar"
  )
)

foo$new()
#> foobar

Created on 2020-10-21 by the reprex package (v0.3.0)

@mattwarkentin
Copy link
Author

Right. But I am not interested in changing how foo is printed, I was hoping to change how members of foo are printed when foo itself is printed (e.g. how an array member is printed).

@gaborcsardi
Copy link
Member

I might be missing something, but can't you just create a format method for your class that formats its members differently?

@mattwarkentin
Copy link
Author

mattwarkentin commented Oct 21, 2020

For sure. That's my fallback plan. Just create a new print method for my class that formats encapsulated members differently than the default print.R6 method. I was just wondering whether I could just define new format methods for members that appear in my class and piggy-back on R6's print method. I'm probably over-engineering the solution...

@mattwarkentin
Copy link
Author

Alright after looking over R6:::print.R6 some more, the issue was with my mental model. format isn't called on members of the R6 object, it is only called on the R6 object itself.

@mattwarkentin
Copy link
Author

For posterity, I think the issue I was facing was beyond my control. In particular, one expects that RStudio uses str() to figure out how to display an object in the Environment pane, but it seems like RStudio has been setup to avoid calling str() on objects of type environment, such as a R6 object (see rstudio/rstudio#7147 and rstudio/rstudio#796).

So this is why I couldn't get my R6 class to show up differently in the pane. Maybe to be solved down the line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants