What is the utility of lexical and dynamic scopes in r?

12

In the Chapter 6 of the book Advanced R there are definitions of the lexical and dynamic scopes. However, I did not understand the utility of knowing these concepts in r . Thus,

  • What is the usefulness of lexical scope in r ?
  • What is the usefulness of the dynamic scope in r ?

The author offers several examples of these forms of scope. But, I reiterate, I need to know the utility of it.

This question can be considered an addendum to this here >. Note that even though SOpt has builder and inheritance issues in other programming languages, some concepts may have lesser or greater employment benefits.

And this is what I want to know: usefulness of lexical and dynamic scopes in r .

    
asked by anonymous 05.01.2019 / 21:01

1 answer

8

These concepts are very important for those who develop R-packets and need to create complex behavioral functions, although for day-to-day data analysis it is not that necessary.

First, to understand the concept of lexical scoping and dynamic scope, I think the best example is as follows:

y <- 100

f <- function(x) {
  y <- 2
  g(x)
}

g <- function(x) { 
  x*y
}

f(5)
[1] 500
g(5)
[1] 500

In R, the scope is lexical, that is, the functions look for the values of the variables in the same environment in which they were defined and not in the environment in which they were called. In the above example, if the scope were dynamic then y would assume the value 2 and the result of f(5) would be 10 . It is important to note that if you change the value of y after the function is created, R will use the new value. For example:

y <- 10
f(5)
[1] 50

That is, R saves where to look for the value of the variable and not the value of the variable when the function is created.

What is the usefulness of the lexical scope? Since a function always accesses variables that are in the scope in which it was defined, can you create functions of the following type?

counter <- function() {
  i <- 0
  function() {
    i <<- i + 1
    return(i)
  }
}
count <- counter()
count2 <- counter()
count()
[1] 1
count()
[1] 2
count()
[1] 3
count()
[1] 4
count2()
[1] 1
count2()
[1] 2
count()
[1] 5

Day by day, this may not be useful, but in rare instances you may need to create functions that have complex behaviors like this.

Another common use is to create functions of type generators , an example is this:

sampling_generator <- function(X_data, Y_data, size) {
  function() {
    rows <- sample(1:nrow(X_data), size, replace = TRUE)
    list(X_data[rows,], Y_data[rows,])
  }
}

This function returns a random sample other than X_data and Y_data each time it is called. This allows you to create very interesting abstractions in your code.

In R, you can also modify these scope scope rules. Modifying these rules can make your function simpler to use. The functions of dplyr make a lot of use of it, for example when we write:

dplyr::mutate(mtcars, cyl = cyl * 2)

In this case, the lexical scope rule was disregarded since the function did not look for the cyl variable in the global environment, where it would have been natural and within mtcars . This code also did not create a cyl variable within the global environment, but within mtcars .

In this case, modifying the scope rule causes the role user to enter much less which can be very useful when doing data analysis.

In summary, in most cases, when we are using functions defined by other developers we do not have to worry about lexical or dynamic scope. At the time of creating packages or functions that will be used by other people we can think about whether we want the lexical scope or modify the scope rules to improve the functions API. We can also abuse these scope rules to create more advanced behavior for functions.

    
07.01.2019 / 14:20