On Nov 23, 2011, at 11:06 PM, Henrik Bengtsson wrote: > Thanks for the quick answer. I didn't know about force() function. >
It doesn't matter how you force the argument, anything - e.g. if(is.environment(envir)) capture.output(...) would do - I used force() just to make the point that it is what is causing it. A more simple example illustrating what happens here: > f = function(e=parent.frame()) local(print(e)) > f() <environment: 0x102f1f470> > f = function(e=parent.frame()) { force(e); local(print(e)) } > f() <environment: R_GlobalEnv> > f = function(e=parent.frame()) if (is.environment(e)) local(print(e)) > f() <environment: R_GlobalEnv> Cheers, Simon > Cheers, > > Henrik > > On Wed, Nov 23, 2011 at 6:56 PM, Simon Urbanek > <simon.urba...@r-project.org> wrote: >> IMHO this has nothing to do with capture.output() per se - it's simply lazy >> evaluation that gets you. Add force(envir) before capture.output and it >> works as you expected - the parent.frame() will be different inside >> capture.output than outside. >> >> Cheers, >> Simon >> >> >> On Nov 23, 2011, at 9:36 PM, Henrik Bengtsson wrote: >> >>> I've noticed the following oddity where capture.output() prevents >>> eval() from evaluating an expression in the specified environment. >>> I'm not sure if it is an undocumented feature or a bug. It caused me >>> many hours of troubleshooting. By posting it here, it might save >>> someone else from doing the same exercise. >>> >>> Start by defining foo() which evaluates an expression locally in a >>> given environment and catches the output via capture.output(): >>> >>> foo <- function(..., envir=parent.frame()) { >>> capture.output({ >>> eval(substitute({x <- 1}), envir=envir) >>> }) >>> } # foo() >>> >>> Then call: >>> >>>> suppressWarnings(rm(x)); foo(envir=globalenv()); print(x); >>> character(0) >>> [1] 1 >>> >>> This works as expected. However, if argument 'envir' is not specified >>> explicitly, you get: >>> >>>> suppressWarnings(rm(x)); foo(); str(x); >>> character(0) >>> Error in str(x) : object 'x' not found >>> >>> which shows that the internal expression of foo() is *not* evaluated >>> in the parent.frame(), i.e. the caller of foo(), which here should be >>> globalenv(). It appears that capture.output() prevents this, because >>> by dropping the latter: >>> >>> foo <- function(..., envir=parent.frame()) { >>> eval(substitute({x <- 1}), envir=envir) >>> } # foo() >>> >>> it works: >>> >>>> suppressWarnings(rm(x)); foo(); str(x); >>> [1] 1 >>> >>> The workaround when still using capture.output() is to force an >>> explicit evaluation of argument 'envir' inside of foo() before: >>> >>> foo <- function(..., envir=parent.frame()) { >>> stopifnot(is.environment(envir)) # Workaround >>> capture.output({ >>> eval(substitute({x <- 1}), envir=envir) >>> }) >>> } # foo() >>> >>> which gives: >>>> suppressWarnings(rm(x)); foo(); str(x); >>> character(0) >>> num 1 >>> >>> This occurs with R v2.14.0 patched and R devel: >>> >>>> sessionInfo() >>> R version 2.14.0 Patched (2011-11-20 r57720) >>> Platform: x86_64-pc-mingw32/x64 (64-bit) >>> >>> locale: >>> [1] LC_COLLATE=English_United States.1252 >>> [2] LC_CTYPE=English_United States.1252 >>> [3] LC_MONETARY=English_United States.1252 >>> [4] LC_NUMERIC=C >>> [5] LC_TIME=English_United States.1252 >>> >>> attached base packages: >>> [1] stats graphics grDevices utils datasets methods base >>> >>>> sessionInfo() >>> R Under development (unstable) (2011-11-20 r57720) >>> Platform: x86_64-pc-mingw32/x64 (64-bit) >>> >>> locale: >>> [1] LC_COLLATE=English_United States.1252 >>> [2] LC_CTYPE=English_United States.1252 >>> [3] LC_MONETARY=English_United States.1252 >>> [4] LC_NUMERIC=C >>> [5] LC_TIME=English_United States.1252 >>> >>> attached base packages: >>> [1] stats graphics grDevices utils datasets methods base >>> >>> /Henrik >>> >>> ______________________________________________ >>> R-devel@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >>> >>> >> >> > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel