Thursday, January 22, 2015

R: Scoping of free variable names

When a function in R uses a 'free' variable -- a variable that is not defined in the function nor an argument of the function -- where R finds the value of the variable can be confusing. Intuitively, we might expect R to use dynamic scoping: the value is found where it is defined in the environment where the function is called or in the nearest environment above that. However, R does not work this way. It uses lexical scoping in which the sequence of environments to look in is determined when the function is defined, but the value is determined when the function is called.

In short:

Where when defined -- what when called.

The following code illustrates the principle:

#
# Scoping
#

a <- "Global"
f <- function() {

g <- function(x) cat( x,a,"\n")
g("called in f before assn of a:")
a <- "in f"
g("called in f after assn of a:")
h <- function(x){
a <- "defined in h"
g(x)
}
h( "h calling g from in f:")
a <- "redefined in f"
h("h calling g in f after redefining a")
rm(a)
h("h calling g after removing a")
}

f()


The output is:

called in f before assn of a: Global
called in f after assn of a: in f
h calling g from in f: in f
h calling g in f after redefining a redefined in f
h calling g after removing a Global

An advantage of lexical scoping over dynamic scoping is that the behaviour of the function is more easily determined when it is defined. If a programmer wishes to use the value of a variable in which the function is called, it merely needs to be included among the arguments to the function.

There is an excellent article by John Fox comparing scoping in R and in S-Plus.

No comments:

Post a Comment