Environments in R, mapply and get

前端 未结 3 835
深忆病人
深忆病人 2021-01-22 17:51

Let x<-2 in the global env:

x <-2 
x
[1] 2

Let a be a function that defines another x locally and

3条回答
  •  伪装坚强ぢ
    2021-01-22 18:34

    The problem is that get looks into the envivornment that its called from but here we are passing get to mapply and then calling get from the local environment within mapply. If x is not found within the mapply local environment then it looks the into the parent environment of that, i.e. into environment(mapply) (which is the lexical environment that mapply was defined in which is the base namespace environment); if it is not there either, it looks into the parent of that, which is the global environment, i.e. your R workspace.

    This is because R uses lexical scoping, as opposed to dynamic scoping.

    We can show this by getting a variable that exists within mapply.

     x <- 2
     b2<-function(){
       x<-1
       mapply(get, "USE.NAMES")
     }
     b2() # it finds USE.NAMES in mapply
     ## USE.NAMES 
     ##     TRUE 
    

    In addition to the workaround involving MoreArgs shown in the question this also works since it causes the search to look into the local environment within b after failing to find it mapply. (This is just for illustrating what is going on and in actual practice we would prefer the workaround shown in the question.)

    x <- 2
    b3 <-function(){
       x<-1
       environment(mapply) <- environment()
       mapply(get, "x")
    }
    b3()
    ## 1
    

    ADDED Expanded explanation. Also note that we can view the chain of environments like this:

    > debug(get)
    > b()
    debugging in: (function (x, pos = -1L, envir = as.environment(pos), mode = "any", 
        inherits = TRUE) 
    .Internal(get(x, envir, mode, inherits)))(dots[[1L]][[1L]])
    debug: .Internal(get(x, envir, mode, inherits))
    Browse[2]> envir
    
    Browse[2]> ls(envir) ### this shows that envir is the local env in mapply
    [1] "dots"      "FUN"       "MoreArgs"  "SIMPLIFY"  "USE.NAMES"
    Browse[2]> parent.env(envir) ### the parent of envir is the base namespace env
    
    Browse[2]> parent.env(parent.env(envir)) ### and grandparent of envir is the global env
    
    

    Thus, the ancestory of environments potentially followed is this (where arrow points to parent):

    local environment within mapply --> environment(mapply) --> .GlobalEnv
    

    where environment(mapply) equals asNamespace("base"), the base namespace environment.

提交回复
热议问题