When to use a reactive expression vs to use <<- to create a global object

526 views Asked by At

I am trying to create a Shiny app using some functions that my coworker created. He often uses the '<<-' operator in his functions to create global objects.

Questions: 1. Is it a good practice to use <<- in this case? 2. Will the app be faster if I use reactive() to represent the objects? 3. Any better suggestions?

Here is an example of the function he wrote:

PrepareData<-function(pickoneperday=TRUE,data) { 
  set.seed(1)
  if (pickoneperday==TRUE) {data <<- PickOnePerDay(data)} 
  data <<- RankData(data)
  SetMeasureType()
  minnodebase <<- 0.005*nrow(data)
  CodeMissingData(data)
}
1

There are 1 answers

2
Enzo On BEST ANSWER

At the outset, I think we need to clarify the scope of the question.

  1. If you write a function in R, it is good practice to return value using either return() at the end of the function, for clarity, or at least putting the data object last before the curly brackets. in this context, the use of <<- can create any sort of errors and complications (in short is a reminder of spaghetti programming, breaking the rule of having a single exit point to the function in question).
  2. Different is the case of shiny special functions. I just like to remind that shiny coders usually does not use return() at the end of a shiny function (even if it would still work). Here either there is no value returned, or reactive is used or other similar constructs.

Part of the confusion comes from the minimal example in the question: the example is not a shiny special function but just a normal function.

In shiny, using for example constructs like observe, it may happen to use <<- to update global objects. A very good example (a great piece of code I often go back to) is the application ShinyChat developed by Jeff Allen, one of shiny developers - see here on github. In this case Jeff uses <<- to update a reactiveValue defined at the global level from within an observe function: very good style.

I conclude with a minor point: if you have any function and you update a variable with <<-, and you have a variable of the same name defined locally, only the global variable is updated. In these cases you need to do something like

data <<- data <- 3

From right to left: the first <- updated the local variable named data: the second <<- updated the global variable named data. Talk about confusing.

On the other hand, in shiny or standard R I never noticed a drastic slowness because of <<-, certainly provided that there aren't too many in the code.

On the issue of alternative techniques like reactive or reactiveValues, please see this good answer on SO to a similar question here.