r-lib / R6

Encapsulated object-oriented programming for R
https://R6.r-lib.org
Other
410 stars 56 forks source link

Escape non-method members with `I()` #222

Open lionel- opened 3 years ago

lionel- commented 3 years ago

So these would be equivalent:

R6::R6Class("class",
  public = list(
    x = I(my_function)
  )
)

R6::R6Class("class",
  public = list(
    initialize = function() self$x = my_function,
    x = NULL
  )
)

Context at r-lib/coro#30.

gaborcsardi commented 3 years ago

So this would be up to the user that implements the R6 class, right? I am not sure how R6 would be able to tell the difference.

lionel- commented 3 years ago

Right, I() would be syntax sugar for the user.

I guess in theory escaping non-methods could be done automatically for functions with a class or with a non-local environment. It'd probably be dangerous to introduce this behaviour now though.

wch commented 3 years ago

@gabor This could work by having the generator look for functions with the AsIs class, and not reassigning the environment for those functions.

How often do you guys think this comes up? I personally haven't encountered a situation where I've wanted to do this. I have wanted Java-style static classes, though, where methods and values exist on the class itself. That could help cases where functions and values need to be shared among members.

For example, it might look something like this:

Foo <- R6Class("Foo",
  static = list(
    x_2 = function() self$x * 2
    x = 1
  ),
  public = list(
    ....
  )
)

Foo$x
#> 1
Foo$x_2()
#> 2

# Can still instantiate objects
a <- Foo$new()

But I think it might be too late to do that at this point, since it would require changing the internal structure of the generator object, but I suspect there's code out there that depends on the existing internal structure.

iqis commented 3 years ago

Can the following work?

This is will inadvertently maintain a reference to the generator. Does this mean that every parent of the generator all the way up to global env will get captured when serializing an instance and is hence hazardous, as mentioned in #225 ?