Reputation: 17
I am trying to understand eval function behaviour inside a function, so assume this is my setting:
Two global variables x and a are defined
x <- 'a'
a <- 'c'
Then a function f is defined with three print statements, I am confused with the fact that eval, envir parameter defaults to parent.frame() but however, if I put it deliberately the results are different. Why?
Below is the code with the comments to understand more, Thanks very much for answers the comments to solve this in advance.
f <- function(x){
## 1st statement, I get it that evaluation should be done in current environment
print(eval(quote(x), envir = environment()))
## 2nd statement, This I don't get, as the default is parent.frame(), shouldn't it be
## evaluated in the calling scope of function which is global environment. As per
## documentation parent.frame() is the default then why this result evaluates to current
## environment, whereas the last print statement when specifically mentions parent.frame gives a different result entirely.
## Note the documentation says: If envir is not specified, then the default is parent.frame() (the environment where the call to eval was made).
## So, my understanding of parent.frame is that it is that frame where calls are happening(basically calling environment), Am I mistaken here?
print(eval(quote(x)))
## 3rd , This behaviour seems okay as parent.frame is referencing the calling scope which is global
print(eval(quote(x), envir=parent.frame()))
}
Output:
#> f(a) #[1] "c" #[1] "c" #[1] "a"
Upvotes: 1
Views: 220
Reputation: 44788
The scoping of supplied arguments and default arguments is different.
Supplied arguments are evaluated in the evaluation frame of the caller, i.e. f
in your example. So the envir is set to the parent.frame
of that call, which is the global environment.
Default arguments are evaluated in the evaluation frame of the function where they are defined, eval
in your example. In the eval()
call, the parent frame is the evaluation frame of f
.
If you think about it a bit, this makes a ton of sense. As author of f()
, you should know what variables are visible while evaluating it, so those are the ones used to evaluate argument expressions. On the other hand, the author of eval()
has no idea what will be available in its callers, so default arguments have to be evaluated in its own evaluation frame.
Upvotes: 2