This is a trivial example I set up to see if I could pass an environment and use the variables in it (this is for a function that will be called many times and might need to use a lot of variables that won't be changing, so it seemed more sensible to use an environment). Here's the code: ######################### #The outer function run.internal.env <- function(x) { in.env <- new.env() assign('x', x, envir=in.env) print(eval(x^2, envir=in.env)) print(ls(envir=in.env)) return(use.internal.env(in.env)) } #The inner function use.internal.env <- function(env) { print(ls(envir=env)) return(eval(x^2, envir=env)) } ########################## Now if I type run.internal.env(2), my output looks like [1] 4 [This is the evaluation in the outer routine] [1] "x" [This is the "ls" from the outer routine] [1] "x" [This is the "ls" from the inner routine] Error in eval(x^2, envir=env): object "x" not found [??? It was listed, so why can't it be evaluated???] If there's anything called "x" in the global environment, it will evaluate that x^2 instead, e.g. x <- 1:3 run.internal.env(2) [1] 4 [This is the evaluation in the outer routine] [1] "x" [This is the "ls" from the outer routine] [1] "x" [This is the "ls" from the inner routine] [1] 1 4 9 Is there any way to force it to use the environment I actually want, and keep all the values I assigned in there? [[alternative HTML version deleted]]
John Tillinghast wrote:> This is a trivial example I set up to see if I could pass an environment and > use the variables in it > (this is for a function that will be called many times and might need to use > a lot of variables that > won't be changing, so it seemed more sensible to use an environment). > > Here's the code: > ######################### > #The outer function > run.internal.env <- function(x) { > in.env <- new.env() > assign('x', x, envir=in.env) > print(eval(x^2, envir=in.env)) > print(ls(envir=in.env)) > return(use.internal.env(in.env)) > } > > #The inner function > use.internal.env <- function(env) { > print(ls(envir=env)) > return(eval(x^2, envir=env)) > } > ########################## > Now if I type > > run.internal.env(2), my output looks like > > [1] 4 [This is the evaluation in the outer routine] > [1] "x" [This is the "ls" from the outer routine] > [1] "x" [This is the "ls" from the inner routine] > Error in eval(x^2, envir=env): object "x" not found [??? It was listed, so > why can't it be evaluated???] > > If there's anything called "x" in the global environment, it will evaluate > that x^2 instead, e.g. > x <- 1:3 > run.internal.env(2) > [1] 4 [This is the evaluation in the outer routine] > [1] "x" [This is the "ls" from the outer routine] > [1] "x" [This is the "ls" from the inner routine] > [1] 1 4 9 > > Is there any way to force it to use the environment I actually want, and > keep all the values I assigned in there?Yes, what you do. You just missed the difference between eval and evalq (been there, done that, got the gray hair...) -- O__ ---- Peter Dalgaard ?ster Farimagsgade 5, Entr.B c/ /'_ --- Dept. of Biostatistics PO Box 2099, 1014 Cph. K (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk) FAX: (+45) 35327907
Gabor Grothendieck
2009-Feb-15 20:47 UTC
[R] Passing environments: why doesn't this work???
Note that you can do things like this too: env$x with(env, x^2) Also its possible you are really getting into object oriented programming without realizing it with the your environments being the objects your functions being the methods. In that case check out the proto package which formalizes all this using environments to implement the prototype model (also called object-based model) of object oriented programming. http://r-proto.googlecode.com On Sun, Feb 15, 2009 at 3:17 PM, John Tillinghast <tilling at gmail.com> wrote:> This is a trivial example I set up to see if I could pass an environment and > use the variables in it > (this is for a function that will be called many times and might need to use > a lot of variables that > won't be changing, so it seemed more sensible to use an environment). > > Here's the code: > ######################### > #The outer function > run.internal.env <- function(x) { > in.env <- new.env() > assign('x', x, envir=in.env) > print(eval(x^2, envir=in.env)) > print(ls(envir=in.env)) > return(use.internal.env(in.env)) > } > > #The inner function > use.internal.env <- function(env) { > print(ls(envir=env)) > return(eval(x^2, envir=env)) > } > ########################## > Now if I type > > run.internal.env(2), my output looks like > > [1] 4 [This is the evaluation in the outer routine] > [1] "x" [This is the "ls" from the outer routine] > [1] "x" [This is the "ls" from the inner routine] > Error in eval(x^2, envir=env): object "x" not found [??? It was listed, so > why can't it be evaluated???] > > If there's anything called "x" in the global environment, it will evaluate > that x^2 instead, e.g. > x <- 1:3 > run.internal.env(2) > [1] 4 [This is the evaluation in the outer routine] > [1] "x" [This is the "ls" from the outer routine] > [1] "x" [This is the "ls" from the inner routine] > [1] 1 4 9 > > Is there any way to force it to use the environment I actually want, and > keep all the values I assigned in there? > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >