1

I'm currently having some issues understanding the behavior of the eval function- specifically the enclos/third argument when an argument isn't supplied to it/ the default argument parent.fame() is used.

name <- function(x){
    print(substitute(x))
    t <- substitute(x)
    eval(t, list(a=7), parent.frame())
}
z <-5
name(a+z)
# returns 12, makes sense because this amounts to
# eval(a+z, list(a=7), glovalenv())


# however the return here makes no sense to me

  name2 <- function(x){
    print(substitute(x))
    t <- substitute(x)
    eval(t, list(a=7)) # third/enclosure argument is left missing
}

z <-5
name2(a+z)
# Also returns 12

I'm having trouble understanding why the second call returns 12. According to my understanding of R, the second call should result in an error because

1) eval's default third argument enclos= parent.frame(), which is not specified.

2) Therefore, parent.frame() is evaluated in the local environment of eval. This is confirmed by Hadley in When/how/where is parent.frame in a default argument interpreted?

3) Thus, the last expression ought to resolve to eval(a+z, list(a=7), executing environment of name)

4) This should return an error because z is not defined in the executing environment of name nor in list(a=7).

Can someone please explain what's wrong with this logic?

Community
  • 1
  • 1
k13
  • 713
  • 8
  • 17
  • the calling environment of name is the global environment in this case, but in general you'd be wrong – k13 Apr 04 '15 at 03:21

1 Answers1

1

z will be available inside the function since it's defined in .GlobalEnv.

Simply put,

name <- function(x) {
  print(z)
}
z <- 5

name(z)

# [1] 5

So while a is still unknown until eval(t, list(a=7)), z is already available. If z is not defined inside name, it will be looked for in .GlobalEnv. What might be counterintuitive is that (a+z) is undefined unless you specify an environment for a. But for z, there is no need to do so.

Dominic Comtois
  • 10,230
  • 1
  • 39
  • 61