Skip to content
Back to formatted view

Raw Message

Message-ID: <CAFDcVCS=OPW_HYfh9BM_ddaXQdLv6hSiD6Bd==pois8jYEc6wg@mail.gmail.com>
Date: 2011-11-24T02:36:38Z
From: Henrik Bengtsson
Subject: capture.output(eval(..., envir)) not evaluate in the expected(?) environment

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