[Rd] `match.call` and dots substitution

Michael Lawrence lawrence.michael at gene.com
Sun Apr 30 19:46:59 CEST 2017


The result of match.call() should be something that would evaluate
correctly in the frame of the fun0() call. While wrapping things in
parentheses is unlikely to cause any problems, arbitrary calls and
symbols would.

Consider the following:

fun0 <- function(a, ...) {
    x <- 2L
    fun1(...)
}
fun1 <- function(b, ...) fun2()
fun2 <- function() {
    mc <- match.call(
        fun1, sys.call(sys.parent()), expand.dots=FALSE,
        envir=parent.frame(2)
    )
    c(correct = eval(mc$b, parent.frame(2)),
      incorrect = evalq(1 + x, parent.frame(2)))
}

x <- 1
fun0(1, 1 + x, 3)
  correct incorrect
        2         3



On Sun, Apr 30, 2017 at 8:30 AM, brodie gaslam via R-devel
<r-devel at r-project.org> wrote:
> I'm noticing some interesting behavior in `match.call` in some corner-ish cases that arise when you try to use `match.call` to match a "grandparent" function and there are dots involved:
>
>
>     fun0 <- function(a, ...) fun1(...)
>        fun1 <- function(b, ...) fun2()
>     fun2 <- function()
>       match.call(
>               fun1, sys.call(sys.parent()), expand.dots=FALSE,
>
>         envir=parent.frame(2)
>       )
>     fun0(1, 2, 3)
>
>     ## fun1(b = 2, ... = pairlist(3))
>
>     fun0((1), (2), (3))   # the parens make the substituted args language
>
>     ## fun1(b = ..1, ... = pairlist(..2))
>
>
> When the values in dots that need to be substituted are language, they get substituted by `..n` where `n` is the position in dots.  When they are scalars they are substituted with the scalar.  It appears this is done in 'R-3.4.0:src/main/unique.c at 1319' in `subDots`:
>
>     while (TYPEOF(t) == PROMSXP)
>             t = PREXPR(t);
>         if( isSymbol(t) || isLanguage(t) )
>       SETCAR(b, installDDVAL(i));
>     else
>       SETCAR(b, t);
>
>
> I'm not sure why it is necessary to use `installDDVAL`, which creates the `..n` symbols, instead of duplicating the language object and attaching that to the matched call.  Certainly from a user perspective I would prefer to see:
>
>     ## fun1(b = (2), ... = pairlist((3)))
>
> instead of:
>
>        ## fun1(b = ..1, ... = pairlist(..2))
>
>
> Do others agree?  Is there a structural reason why this cannot be done?  Note this behavior has been this way since at least R3.0 and probably earlier.
>
>
> Best regards,
>
> B.
>
> PS: sessionInfo():
>
> R version 3.4.0 (2017-04-21)
> Platform: x86_64-apple-darwin15.6.0 (64-bit)
> Running under: macOS Sierra 10.12.3
>
> Matrix products: default
> BLAS: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRblas.0.dylib
> LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
>
> locale:
> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
>
> attached base packages:
> [1] stats     graphics  grDevices utils     datasets  methods   base
>
> loaded via a namespace (and not attached):
> [1] compiler_3.4.0
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list