Reputation: 10954
I was trying to evaluate some expressions in a function using eval
but it would run into an error trying to find the objects which were defined in the function scope.
I realized that this was because eval
's default environment is parent.frame()
. Is there a good reason for this? I would expect it to be the same as, say, assign
, that is, the current environment.
Here is an example (per Gabor's request):
fnFoo = function() {
# assign 10 variables
for(i in 1:10) assign(paste('v', i, sep = ''), rnorm(10))
# find the variables by name and evaluate them
Map(sum, lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)), eval))
}
# test that eval is unable to find a variable declared in the function scope
fnFoo()
However, changing the function to
fnFoo = function() {
# assign 10 variables
for(i in 1:10) assign(paste('v', i, sep = ''), rnorm(10))
# find the variables by name and evaluate them
# Map(sum, lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)), eval))
Map(sum, lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)), function(x) eval(x, envir = environment())))
}
# now it works
fnFoo()
works.
Thanks.
Upvotes: 0
Views: 681
Reputation: 9344
Your problem is that you are being too clever with your lapply
in conjuction with eval
. Let's expand what is happening.
lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)), eval)
is equivalent to
lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)),
function(x) eval(x))
However, a separate scope gets created for function(x) eval(x)
, which no longer has v1
, v2
, etc. in its immediate environment. Thus, you want to tell eval
in conjunction with lapply
to use the correct environment:
lapply(parse(text = grep('v', ls(envir = environment()), value = TRUE)),
eval, envir = environment())
By the way, another approach is
apply(sapply(grep('v', ls(envir = environment()), value = TRUE), get, envir = environment()), 1, sum)
Upvotes: 1