From hb at biostat.ucsf.edu  Thu Nov 24 03:36:38 2011
From: hb at biostat.ucsf.edu (Henrik Bengtsson)
Date: Wed, 23 Nov 2011 18:36:38 -0800
Subject: [Rd] capture.output(eval(...,
	envir)) not evaluate in the expected(?) environment
Message-ID: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>

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



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