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

'self' triggers 'no visible binding for global variable' #230

Open
James-G-Hill opened this issue May 18, 2021 · 9 comments
Open

'self' triggers 'no visible binding for global variable' #230

James-G-Hill opened this issue May 18, 2021 · 9 comments

Comments

@James-G-Hill
Copy link

When defining an R6 object within a package, running 'Check' will cause 'self' to trigger 'no visible binding for global variable' message.

One way to fix it is:

if(getRversion() >= "2.15.1")  utils::globalVariables(c("self"))

Is there any other solution more targeted to a specific function rather than defined globally?

@gaborcsardi
Copy link
Member

FWIW I don't think you need any workarounds if you define your methods "inline".

E.g. here is a simple example: https://github.com/r-lib/progress/blob/master/R/progress.R#L179

@B-Fernandez
Copy link

B-Fernandez commented May 18, 2021

Hey @gaborcsardi, thanks for coming back to this. I'm working with @James-G-Hill on this one.

Might have misunderstood 'inline', if the reprex below isnt inline please do correct me :)
The major difference between this example and the progress bar one is that the below is within a function.

#' func
#' @param ... opts
#' @examples
#'\dontrun{
#' obj_gen(bar = "fubar")
#'}
#'
obj_gen <- function(...){

  obj <- R6::R6Class("my_class",
              public = list(
                foo = NULL,
                initialize = function(bar = NA){
                  self$foo <- bar
                },
                print = function(){
                  cat("Anyone for ",
                      self$foo,
                      "?",
                      sep = "")
                }
              )
  )
  obj$new(...)
}

The note and warning is only generated when self is called in a function, ie in print, but not in initialise.

@gaborcsardi
Copy link
Member

In this case you can put self <- NULL within the function as a workaround:

obj_gen <- function(...){
  self <- NULL
  obj <- R6::R6Class("my_class",
              public = list(
  ...

@B-Fernandez
Copy link

That solves it. Its more explicit than:
if(getRversion() >= "2.15.1") utils::globalVariables(c("self"))

Thanks,

@gtm19
Copy link

gtm19 commented Jun 16, 2021

FYI - same issue for private, solved the same way:

obj_gen <- function(...){
  self <- NULL
  private <- NULL
  obj <- R6::R6Class("my_class",
              public = list(
  ...

@JosiahParry
Copy link

FWIW I'm running into this as well. I define the methods in standalone functions because they are 50+ lines each and inlining them makes an already massive object definition even more so. In my case I cannot include self <- NULL because the functions are not defining an R6 class but rather are used as active bindings.

@gaborcsardi
Copy link
Member

IMO think it is not worth getting into active bindings and such, they are fragile in various circumstances. The straightforward way I linked above at #230 (comment) should work better.

@JosiahParry
Copy link

To make sure I understand the approach in the above comment it is roughly this:

  • define utility functions with self, private
  • in the methods / bindings create inline function calls
  • inline functions pass self, private and other args to the utility functions

e.g.

helper <- function(self, private) {
  # do stuff
}
my_class <- R6::R6Class(
  "my_class", 
  public = list(
    method = function() {
      helper(self, private)
    }
  )
)

and as an aside, i'm using active bindings to provide visibility to values of private without being able to modify the values. from what i can tell, if a property is public it is also modifiable by the user.

@gaborcsardi
Copy link
Member

i'm using active bindings to provide visibility to values of private without being able to modify the values. from what i can tell, if a property is public it is also modifiable by the user.

The user will always be able to modify private through the original binding. There is no way in R to really lock it down AFAICT.

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

5 participants