Writing functions in R, keeping scoping in mind Writing functions in R, keeping scoping in mind r r

Writing functions in R, keeping scoping in mind


If I know that I'm going to need a function parametrized by some values and called repeatedly, I avoid globals by using a closure:

make.fn2 <- function(a, b) {    fn2 <- function(x) {        return( x + a + b )    }    return( fn2 )}a <- 2; b <- 3fn2.1 <- make.fn2(a, b)fn2.1(3)    # 8fn2.1(4)    # 9a <- 4fn2.2 <- make.fn2(a, b)fn2.2(3)    # 10fn2.1(3)    # 8

This neatly avoids referencing global variables, instead using the enclosing environment of the function for a and b. Modification of globals a and b doesn't lead to unintended side effects when fn2 instances are called.


There's a reason that some languages don't allow global variables: they can easily lead to broken code.

The scoping rules in R allow you to write code in a lazy fashion - letting functions use variables in other environments can save you some typing, and it's great for playing around in simple cases.

If you are doing anything remotely complicated however, then I recommend that you pass a function all the variables that it needs (or at the very least, have some thorough sanity checking in place to have a fallback in case the variables don't exist).

In the example above:

The best practise is to use fn1.

Alternatively, try something like

 fn3 <- function(x)   {      if(!exists("a", envir=.GlobalEnv))      {         warning("Variable 'a' does not exist in the global environment")         a <- 1      }      if(!exists("b", envir=.GlobalEnv))      {         warning("Variable 'b' does not exist in the global environment")         b <- 2      }      x + a + b   }


Does the problem come about when you're just using a global variable in a function or when you try to assign the variable? If it's the latter I suspect it's because you're not using <<- as an assignment within the function. And while using <<- appears to be the dark side 1 it may very well work for your purposes. If it is the former, the function is probably masking the global variable.

Naming global variables in a manner that it would be difficult to mask them locally might help. e.g.: global.pimultiples <- 1:4*pi