Open In App

Lexical Scoping in R Programming

Lexical Scoping in R programming means that the values of the free variables are searched for in the environment in which the function was defined. An environment is a collection of symbols, value, and pair, every environment has a parent environment it is possible for an environment to have multiple children but the only environment without the parent is the empty environment. If the value of the symbol is not found in the environment in which the function was defined then the search is continued in the parent environment. In R, the free variable bindings are resolve by first looking in the environment in which the function was created. This is called Lexical Scoping.

Why Lexical Scoping?

Lexical Scoping is a set of rules that helps to determine how R represents the value of a symbol. It is an in-built rule in R which automatically works at the language level. It is mostly used to specify statistical calculations. Lexical scoping looks up to symbol based on how functions were nested initially when they were created and not on how they were nested when they called upon. When we use lexical scoping we don’t have to know how the function is called and to figure out where the value of the variable will be looked upon. We only have to look at the function’s definition.



Lexical meaning in lexical scoping is completely different from usual English definition which means relating to words or vocabulary of a language which is distinguished from grammar and construction rather it comes from computer science term lexing meaning by which process that converts code represented as text to meaningful pieces which is comprehensible by programming language. Consider the following example:




f <- function(x, y)
{
  x * y * z
}

In this:



Therefore, the scoping rules of the language determine how values are assigned to free variables. Free variables are not formal arguments and not local variables that are assigned inside of the function body.

Principles of Lexical Scoping

There are four basic principles behind R’s implementation of lexical scoping:

  1. Name Masking
  2. Functions vs variables
  3. A fresh start
  4. Dynamic Lookup

Let’s discuss each principle one by one.

Name Masking

The following example illustrates the most basic principle of lexical scoping, and you should have no problem predicting the output.

Functions vs Variables

The same principles apply regardless of the type of associated value — finding functions works exactly the same way as finding variables:
Example:




a <- function(x) 10 * x
b <- function(){
  a <- function(x) x + 10
  a(12)
}
b() 

Output:

[1] 22

A Fresh Start

When a function is called, a new environment is created every time. Each acknowledgement is completely independent because a function cannot tell what happened when it was run last time.
Example:




a <- function(){
  if(!exists("z"))
  {
    z <- 10
  }
  else
  {
    z <- z+10
  }
  z
}
a()

Output:

[1] 10

Dynamic Lookup

Lexical scoping controls where to look for values not when to look for them. R looks for the values when the function is executed not when it is created. The output of the function can be different depending on objects outside its environment.
Example:




g <- function() x^3
x <- 10
g() 

Output:

[1] 1000

There is a function in R which is findGlobals() from codetools and it helps us to find all global variables being used in a function and lists all the external dependencies of a function. findGlobals() find the global variables and functions which are used by the closure.
Example:




aGlobal <- rnorm(10)
bGlobal <- rnorm(10)
  
f <- function()
  a <- aGlobal
  b <- bGlobal
  plot(b ~ a)
}
codetools::findGlobals(f) 

Output:

[1] "{"       "~"       "<-"      "aGlobal" "bGlobal" "plot"

We can manually change the environment to the empty environment emptyenv(). emptyenv() is a totally empty environment.


Article Tags :