Chapter 14 R6

14.2 Classes and methods

Any … R6 method called for its side effects … should return invisible(self).

WHY? What is invisible(self) doing in the add function below? I tried removing this line but it doesn’t change the output…

Returning self or invisible(self) allows for method chaining. i.e. x$add(1)$add(2) can be done rather than x$add(1); x$add(2). In the absence of anything better to return, why not return itself

14.2.2 Important methods

Why don’t we need to specifically call haldey2$print to see the output below)? Is the print method just a built in output of an R6 object?

Person: 
  Name: Hadley
  Age:  NA

Print is an S3 generic, so when print is implicitly called, it calls the method for the R6 object. The method for the R6 object is “look for a print function inside the R6 object”

Classes and methods 14.2.3

Once instantiated, can you add another method to an R6 object or does the set function only work on the R6 generator?

Once instantiated the environments are locked (no new bindings). But, you can fudge with things and still modify existing bindings if you wanted. But, this is not really something to advocate:

[1] "R6ClassGenerator"
h@xed

You can also set the lock_objects option on the generator to FALSE

## [1] 5
[1] 5

But this still won’t work because the bindings were still locked

#> Error in beer$percent_abv <- function() {: cannot change value of locked binding for 'percent_abv'

Exercises 14.2.6.4

Why can’t we use method chaining to access the current time zone?

[1] "America/Los_Angeles"
Error in tz$set("Antarctica/South_Pole")$get : 
  $ operator is invalid for atomic vectors

You’re not returning an R6 object in your first “set”, you’re returning a character vector, so you can’t find the get method of that character vector

We can return something using the following code:

That said, not every function should support chaining. Sometimes you want the function to return some value (like $get) and in these cases, you just won’t be able to chain, and that is okay.

14.4 Reference semantics

$clone() does not recursively clone nested R6 objects. If you want that, you’ll need to use $clone(deep = TRUE).

Can we see this in action using a subclass?

This example is taken from the R6 documentation:

Object c1 contains s, which we will clone. The original and clone both point to the same object, and by using deep = TRUE we can modify s in one object without changing it in the other.

When or why would I set the clone argument to FALSE?

Clone has a large memory footprint so if you’re going to create a lot of R6 methods you may want to exclude this!