Open In App

Lexical Scoping in R Programming

Last Updated : 16 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Lexical scoping means R decides where to look for a variable based on where the function was written (defined), not where it is called.

When a function runs and it sees a variable, R checks:

  • Inside the function, is the variable there?
  • If not, it looks in the environment where the function was created.
  • Then it keeps moving up — one level at a time — until it finds the variable or reaches the global environment.

Consider the following example:

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

In this:

  • x and y are formal arguments
  • z as the free variable

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.

If variable is not defined inside the function:

Example:

R
c <- 10
f <- function(a, b)
{
  a + b + c
}
f(8, 5) 

Output
[1] 23

It takes the c value as 10 and then adds these numbers and finally we are having 23 as output.

If name is not defined inside the function: If a name isn’t defined inside a function, R will look one level up. Example:

R
a <- 10
b <- function()
{
  c <- 11
  c(a, c)
}
b() 

Output
[1] 10 11

When one function is defined inside another function:

The same rules apply if a function is defined inside another function: look inside the current function, then where that function was defined, and so on, all the way up to the global environment, and then on to other loaded packages. Example:

R
a <- 10
g <- function(){
  b <- 20
  h <- function(){
    c <- 30
    c(a, b, c) 
  }
  h()
}
g()

Output
[1] 10 20 30

When functions are created by another function:

The same rules apply to closures, functions created by other functions. Example:

R
a <- function(z){
  b <- 10
  function(){
    z + 4 * b
  }
}
x <- a(10)
x() 

Output
[1] 50

R returns the accurate value of b after calling the function because x preserves the environment in which it was defined. The environment includes the value of b.

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:

R
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:

R
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:

R
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:

R
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.



Next Article
Article Tags :

Similar Reads