Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scoping and evaluating functions in R

Tags:

r

scoping

Given the following function

f <- function(x) {
    g <- function(y) {
            y + z
    }
    z <- 4
    x + g(x)
 }

If one runs the following code in R why is the answer 10? I'm a little confused about how y plays into this question.

z <- 10
f(3)
like image 570
nzhanggh Avatar asked Mar 12 '20 22:03

nzhanggh


People also ask

What is scoping in R?

The scoping rules of the language define how value is assigned to free variables. R uses lexical scoping, which says the value for z is searched for in the environment where the function was defined. Note: Lexical scoping is also referred to as statical scoping.

What is a scoping function?

What are scope functions? In Kotlin, scope functions are used to execute a block of code within the scope of an object. Generally, you can use scope functions to wrap a variable or a set of logic and return an object literal as your result. Therefore, we can access these objects without their names.

What is the use of options () function in R?

options() function examines a variety of global options which affect the way in which R computes and displays its results. ... : any options can be defined, using name = value. However, only the ones below are used in base R. Options can also be passed by giving a single unnamed argument which is a named list.

What is the difference between static and dynamic scoping?

To sum up, in static scoping the compiler first searches in the current block, then in global variables, then in successively smaller scopes. Dynamic Scoping: With dynamic scope, a global identifier refers to the identifier associated with the most recent environment and is uncommon in modern languages.


1 Answers

R uses lexical scoping which means that if an object is referenced but not defined in a function then it is looked for in the environment in which the function is defined, not the environment from which it was called.

z is referenced in g but is not defined in g so it looks to the environment in which g is defined and that is the environment within f so g uses z = 4.

Actually in this case the environment that g is defined in is the same as the environment from which g is called so any way you look at it z = 4 must be used. If functions defaulted to the global environment to look for objects not defined in the function then it would use z = 10 but that is not how R works.

Making it work differently

If for some reason you wanted to force g to look for z in the environment in which f is called then you could do this (where parent.frame() refers to the environment from which f is called).

f2 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + with(envir, z)
    }
    z <- 4
    x + g(x)
 }
 z <- 10
 f2(3)
 ## [1] 16

or we could use y + envir$z except that that would only look in the parent frame and not in its ancestors whereas with will look in ancestors of the parent frame if not found in the parent frame.

An alternative is to change g's environment like this so that it looks into envir for objects not found in g:

f3 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + z
    }
    environment(g) <- envir
    z <- 4
    x + g(x)
 }
 z <- 10
 f3(3)
 ## [1] 16
like image 120
G. Grothendieck Avatar answered Oct 27 '22 03:10

G. Grothendieck