Open In App

Dynamic Scoping in R Programming

R is an open-source programming language that is widely used as a statistical software and data analysis tool. R generally comes with the Command-line interface. R is available across widely used platforms like Windows, Linux, and macOS. Also, the R programming language is the latest cutting-edge tool. The scoping rules for R are the main feature that makes it different from the original S language. R language uses lexical scoping or static scoping. A common alternative is Dynamic scoping.

Concept Behind Dynamic Scoping

Consider the following function:






f <- function(x, y)
{
   x^2 + y/z
}

This function has 2 formal arguments x and y. In the body of the function, there is another symbol z. In this case, z is a free variable. The scoping rules of a language determine how values are assigned to free variables. Free variables are not formal arguments and are not local variables (assigned inside the body). Lexical scoping in R means that the values of free variables are searched for in the environment in which the function was defined. Searching for the value of the free variable means:

Dynamic Scoping in R Programming

Typically a function is defined in the global environment so that the value of free variables is just found in the user’s workspace however in R one can have functions defined inside other functions. For example, have a look at the below code. 






make.power <- function(n){
  pow <- function(x){
    x = x^n
  }
  pow
}
 
cube <- make.power(3)
square <- make.power(2)
print(cube(3))
print(square(3))

Output

[1] 27
[1] 9

The power function takes the argument x and raised the power n. So that makes the function pow return inside the function value. n is a free variable and is defines in the pow function. What’s in a function environment? 




ls(environment(cube))

[1] "n"   "pow"

This code assumes that the R environment has a specified object called a cube. The items in a given environment can be listed using the ls() method. The environment of the cube, which is acquired using the environment() function, is the argument to ls() in this instance.




get("n", environment(cube))

[1] 3

The value of n is retrieved from the environment of the cube using the get() function, presuming an object named n is declared within that environment.
 




ls(environment(square))

[1] "n"   "pow"

This code expects that the R environment has defined an object called a square. The items in a given environment can be listed using the ls() method. The environment of the square, which was acquired via the environment() function, is the argument to ls() in this instance.




get("n", environment(square))

[1] 2

When you type get(“n”, environment(square)), you’re attempting to retrieve the value of n from the square’s environment. Since Square’s environment does not specify n.

Let’s consider another example:




y <- 10
 
# creating a function f which takes argument x
f <- function(x){
  # y is free variable
  y <- 2 
   
  # g function is also a free variable
  # not defined in the scope of function
  y^2 + g(x) 
}
 
g <- function(x){
  # y is free variable
  # value of y in this function is 10
  x*y
}

What is the value of y in this case? 

When a function is defined in the global environment and is subsequently called from the global environment, then the defining environment and the calling environment are the same. This can sometimes give the appearance of dynamic scoping. 




g <- function(x){
  a <- 3
  # in this case x is function a formal argument and
  # a is local variable and
  # y is free variable
  x + a + y
}
 
# printing value of g(2)
print(g(2))

If we call g(2) it will give an error like the following:

Output

Error in g(2) : object 'y' not found

After assigning value to y call g(2) as follows: 




g <- function(x){
  a <- 3
  x + a + y
}
 
# assigning value to y
y <- 3
 
# print g(2)
print(g(2))

Output

[1] 8

Article Tags :