[R] Use of ellipsis

Bert Gunter bgunter@4567 @end|ng |rom gm@||@com
Fri May 27 17:45:03 CEST 2022


I think we're getting confused here. substitute() and quote() are
different. Your original suggestion used substitute(). eval() works
here as intended with the default env argument:

f <- function() {
   x <- 'function'
   list(qu = eval(quote(x), parent.frame()),
        defqu = eval(quote(x)),
        sub = eval(substitute(x), parent.frame()),
        defsub = eval(substitute(x))
   )

> f()
$qu
[1] "caller"

$defqu
[1] "function"

$sub
[1] "function"

$defsub
[1] "function"
}

So, there are 2 separate questions here:
1) What is the difference between substitute() and quote()
2) Why does eval() work differently with quote() with and without the
default 'parent.frame()' argument?

Herewith my understanding. Please **do** correct errors.

1. quote() just quotes its argument. quote(x) := x, (a 'name' language object.)
x is a bound symbol in the default evaluation environment, so
substitute(x) replaces x with its value. Hence eval() does nothing to
it with or without explicitly providing the default.

2.  Consider:
g1 <- function() {
   x <- 'function'
   eval(quote(x))
}

g2 <- function() {
   x <- 'function'
   eval(quote(x), env= parent.frame())
}

> g1()
[1] "function"
> g2()
[1] "caller"

This looks like to me a case of delayed assignment. In g1, the default
value of parent.frame() is a **promise**, and is not evaluated until
eval() is called, at which time the parent.frame is the environment of
g2, where x = 'function' . In g2, the env argument, parent.frame(),
is explicitly given and so is immediately evaluated in the environment
of g2, whose parent is .GlobalEnv where x lives as the value 'caller'.

HTH (and that I haven't screwed things up),

Bert




Bert Gunter

"The trouble with having an open mind is that people keep coming along
and sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )

On Thu, May 26, 2022 at 11:24 PM Ivan Krylov <krylov.r00t using gmail.com> wrote:
>
> On Thu, 26 May 2022 15:51:38 -0700
> Bert Gunter <bgunter.4567 using gmail.com> wrote:
>
> > FWIW, you don't need to explicitly provide parent.frame() as it's the
> > default of the 'envir' argument of eval anyway.
>
> Unfortunately, there's a difference between evaluating parent.frame()
> explicitly when calling eval() and letting eval() evaluate
> parent.frame() as the default value of the envir argument. What I could
> have used here is eval.parent():
>
> x <- 'caller'
> f <- function() {
>  x <- 'function'
>  list(
>   eval = eval(quote(x)),
>   explicit.parent = eval(quote(x), parent.frame()),
>   eval.parent = eval.parent(quote(x))
>  )
> }
> f()
> # $eval
> # [1] "function"
> #
> # $explicit.parent
> # [1] "caller"
> #
> # $eval.parent
> # [1] "caller"
>
> --
> Best regards,
> Ivan



More information about the R-help mailing list