0
votes

Consider the following piece of code:

greet <- function(object) {
        greeting <- "hola"
        UseMethod("greet", object)
}

greet.character <- function(object)
        paste(greeting, object)

greet("stackoverflow")
#> [1] "hola stackoverflow"

Created on 2021-02-03 by the reprex package (v0.3.0)

Evidently, the execution environment of greet.character method is populated with the variables created in the generic, before UseMethod(), so that the code works as expected.

However, including these definitions in a package will lead to the following NOTE upon R CMD check:

> checking R code for possible problems ... NOTE
  greet.character: no visible binding for global variable ‘greeting’
  Undefined global functions or variables:
    greeting

You can find an example package illustrating the issue at this repository.

Now, I am aware that I can shut up the NOTE with globalVariables(), but I am still puzzled about the origin of the NOTE in the first place. So my questions are:

  1. Is there any intrinsic reason why the example above should be considered "bad practice" in an R package? In a real life example, I'm using a construct like this to avoid code repetition in several methods.

  2. If not, is there any better option than using globalVariables()?

1

1 Answers

0
votes

Answering myself, I think this practice can lead to confusing behaviour since UseMethod() generates a call of the appropriate method with its same arguments; implying that modifications to a variable which is an argument of the generic (not like greeting in my example above) are not propagated to the method.

Right now I'm defining extra functions to be called at the beginning of each method to perform the complex computation I was originally doing in the generic. This can also lead to cumbersome code if these functions require many arguments, but is the best solution I have found so far.

I will leave this open for some time to see if someone has other approaches to propose.