1

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)
}
Ketty
  • 811
  • 10
  • 21
  • 2
    Why does your co-worker do this? It makes re-using functions very difficult. And you're really only concerned with "faster" here? And not "correct"? A more complete [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – MrFlick Aug 29 '17 at 19:46
  • 4
    `reactive()` and `<<-` do two very different things. `reactive()` allows a thing (data frame for example) to react to user input. `<<-` as you say assigns global objects. They are not really interchangeable. Also, I don't really understand why your coworker does that. – John Paul Aug 29 '17 at 19:48
  • Thanks for your input. The app runs noticably slow so I wonder if him using << explains the slowness. It looks like a better practice would be to rewrite the function (by avoiding <<) instead of using reactive(). Any other suggestions are welcome and appreciated. – Ketty Aug 29 '17 at 19:54
  • 2
    Agree with other commenters - you should not adopt your coworker's practice. If you need to return objects from a function the correct way to do it is to use `return(data)`. Otherwise you're just asking for monstrously confusing bugs down the road. – HFBrowning Aug 29 '17 at 19:55
  • "Is it a good practice to use `<<-`...": **NO**. You can also have multiple reactive values update after an event by having them depend on one another, so each can be directly assigned in the server loop. – Nathan Werth Aug 29 '17 at 21:06
  • ShinyChat is an interesting example. It uses both global and session reactiveValues not because those are 'good style', but because those are what the app requires. A chat app needs to share live data (chat text, users) between different users in different sessions. `<<-` is used to update the value of a global object in the global (shared) environment. When first created, vars is defined using `<-`, and global objects can be updated in the session/local environment using `<-`. Use global variables only if your app requires them. Use `<<-` or `<-` depending on the scope/environment. – Brian D Dec 18 '19 at 21:36

1 Answers1

2

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.

Enzo
  • 2,543
  • 1
  • 25
  • 38