FAQ
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

Search Discussions

  • Simon Urbanek at Nov 24, 2011 at 2:56 am
    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
  • Henrik Bengtsson at Nov 24, 2011 at 4:06 am
    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
    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
  • Simon Urbanek at Nov 24, 2011 at 2:21 pm

    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
    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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupr-devel @
categoriesr
postedNov 24, '11 at 2:36a
activeNov 24, '11 at 2:21p
posts4
users2
websiter-project.org
irc#r

2 users in discussion

Simon Urbanek: 2 posts Henrik Bengtsson: 2 posts

People

Translate

site design / logo © 2023 Grokbase