0
z <- 1
a <- function() {
  print(parent.frame())
  eval(quote({print(z)}))
}
b <- function() {
  z <- 2
  print(environment())
  a()
}
b()
# output:
<environment: 0x55f0020b1af0>
<environment: 0x55f0020b1af0>
[1] 1

According to documentation:

Usage

eval(expr, envir = parent.frame(),
           enclos = if(is.list(envir) || is.pairlist(envir))
                       parent.frame() else baseenv())

Since the envir argument defaults to parent.frame(), which is the environment of function b, it is the z inside of b that is supposed to be printed. But rather it is the z in the global environment that is printed.

  • 1
    Note that default parameters are evaluated in the running function environment but parameters you pass in are evaluated in the calling environment. So you get a very different `parent.frame()` if you pass it in as a parameter vs if you use the default value. Try `evalq(print(z), envir=parent.frame())` instead of the `eval()` you currently have. – MrFlick Oct 24 '20 at 02:16

1 Answers1

3

The parent frame of eval is the caller of eval, not the caller of a.

# same as eval except for addition of print statement
my.eval <- function (expr, envir = parent.frame(), enclos = if (is.list(envir) || 
    is.pairlist(envir)) parent.frame() else baseenv())  {
  print(envir)
  .Internal(eval(expr, envir, enclos))
}

z <- 1
a <- function() {
  print(environment())
  my.eval(quote({print(z)}))
}

b <- function() {
  z <- 2
  a()
}
b()
## <environment: 0x000000000b208d20>
## <environment: 0x000000000b208d20>
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341