r-lib / R6

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

Remove active binding in class generator #185

Closed iferres closed 5 years ago

iferres commented 5 years ago

Hi, quick question. I was wondering if there's any way to remove an active binding (or any type of field) using something like MyR6Class$set() (but the opposite). In the same way I can add functions/fields/bindings, I would like to remove them if needed. I tried setting a previously added active binding to NULL but it didn't work. Thanks!

shrektan commented 5 years ago

Dynamically change an object's fields seems unintuitive (at least to me).

Of course, it's possible by hacking (see the example code below) but I suggest create a field which is an environment and bind functions there...

The hacking code....

proto <- R6::R6Class(
  active = list(
    f1 = function() rnorm(1),
    f2 = function() rnorm(2)
  ),
  public = list(
    rm_bindings = function(x) {
      unlockBinding(x, env = self)
      makeActiveBinding(x, function() NULL, env = self)
      lockBinding(x, self)
    }
  )
)

obj <- proto$new()
obj$f1
#> [1] -0.7540934
obj$f2
#> [1]  0.3585274 -1.2203444
obj$rm_bindings('f1')
obj$f1
#> NULL
obj$f2
#> [1] -1.0596080  0.8594399

Created on 2019-03-10 by the reprex package (v0.2.1)

wch commented 5 years ago

I think @iferres is talking about removing something from the class (proto in your example), not from an instance of the class (obj). @iferres is that correct?

iferres commented 5 years ago

Thanks both @shrektan and @wch , for your answers. Yes, I was asking how to remove something from the class, as @wch have pointed out.

shrektan commented 5 years ago

Similar hack...

proto <- R6::R6Class(
  active = list(
    f1 = function() rnorm(1),
    f2 = function() rnorm(2)
  )
)

obj <- proto$new()
obj$f1
#> [1] -1.128665
obj$f2
#> [1] 0.9919912 0.5682875
proto$active$f1 <- NULL
obj2 <- proto$new()
obj2$f1
#> NULL
obj2$f2
#> [1]  2.007603 -1.158038

Created on 2019-03-16 by the reprex package (v0.2.1)

iferres commented 5 years ago

I tried this but I don't see possible to access $active. All active bindings are set as public, and I can't set an active binding to NULL (throws error). What I would like to achieve is to "reset" a class with default methods/fields/bindings (i.e. with only those which the class comes out of package, without the ones manually added after loading it), may be there's a better way to accomplish that. I'm using R6 version 2.4.0.

shrektan commented 5 years ago

I don’t understand what you mean. Can you run the example code above? Or you can, but you can’t change a r6class from a loaded R package ? Or?

iferres commented 5 years ago

Oh, sorry, I misunderstood your argument. It works as expected and solve my problem. Thanks!