Jon Claus
Jon Claus

Reputation: 2932

Inconsistency with R's Global Environment in a function call

I was playing around with R and noticed some inconsistencies with the Global Environment surrounding function calls differing from the actual global environment.

Consider the following:

> test = function () 
+ {
+     print(environmentName(as.environment(-1)))
+     print(ls(as.environment(-1)))
+     print(environmentName(.GlobalEnv))
+     print(ls(.GlobalEnv))
+     as.environment(-1)
+ }
> foo = 1
> ls()
[1] "foo"  "test"
> test()
[1] ""
[1] "doTryCatch" "expr"       "handler"    "name"       "parentenv" 
[1] "R_GlobalEnv"
[1] "foo"  "test"
<environment: R_GlobalEnv>

Within the function call, as.environment(-1) returns an environment that claims it is <environment: R_GlobalEnv> but when calling environmentName on said environment, its name is an empty character. Furthermore, the contents of it differ from what is in the true global environment. What exactly is going on here?

I first noticed the error using mget within a call, as a variable defined globally could not be found. This seems counter-intuitive because normally when referencing a variable within a function, R will search upwards in the enclosing environments until it finds a definition for a variable, including the global environment.

Upvotes: 9

Views: 231

Answers (1)

hadley
hadley

Reputation: 103898

This is a consequence of lazy evaluation:

test <- function () {
  e <- as.environment(-1)

  list(
    lazy = ls(as.environment(-1)), 
    eager = ls(envir = e)
  )
}

foo <- 1
test()
#> $lazy
#> [1] "doTryCatch" "expr"       "handler"    "name"       "parentenv" 
#> 
#> $eager
#> [1] "foo"  "test"

Upvotes: 4

Related Questions