From simon.urbanek at r-project.org  Thu Nov 24 15:21:33 2011
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Thu, 24 Nov 2011 09:21:33 -0500
Subject: [Rd] capture.output(eval(...,
	envir)) not evaluate in the expected(?) environment
In-Reply-To: <CAFDcVCR5r=jiEDV-Ga5PYrLDwvmd8oW59VKdG1R5moTKq6KfqQ@mail.gmail.com>
References: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>
	<62B71EB4-EAE3-40BA-BB29-769E9C4C1A2D@r-project.org>
	<CAFDcVCR5r=jiEDV-Ga5PYrLDwvmd8oW59VKdG1R5moTKq6KfqQ@mail.gmail.com>
Message-ID: <CA55943D-D720-4114-B509-AE271D9231CA@r-project.org>


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.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
Simon Urbanek