From hb at biostat.ucsf.edu  Thu Nov 24 05:06:17 2011
From: hb at biostat.ucsf.edu (Henrik Bengtsson)
Date: Wed, 23 Nov 2011 20:06:17 -0800
Subject: [Rd] capture.output(eval(...,
 envir)) not evaluate in the expected(?) environment
In-Reply-To: <62B71EB4-EAE3-40BA-BB29-769E9C4C1A2D@r-project.org>
References: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>
	<62B71EB4-EAE3-40BA-BB29-769E9C4C1A2D@r-project.org>
Message-ID: <CAFDcVCR5r=jiEDV-Ga5PYrLDwvmd8oW59VKdG1R5moTKq6KfqQ@mail.gmail.com>

Thanks for the quick answer.  I didn't know about force() function.

Cheers,

Henrik

On Wed, Nov 23, 2011 at 6:56 PM, Simon Urbanek
<simon.urbanek at 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 at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>
>



[Rd] capture.output(eval(..., envir)) not evaluate in the expected(?) environment
Henrik Bengtsson