From simon.urbanek at r-project.org  Thu Nov 24 03:56:55 2011
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Wed, 23 Nov 2011 21:56:55 -0500
Subject: [Rd] capture.output(eval(...,
	envir)) not evaluate in the expected(?) environment
In-Reply-To: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>
References: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>
Message-ID: <62B71EB4-EAE3-40BA-BB29-769E9C4C1A2D@r-project.org>

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