Question

If only the named arguments of a S4 generic function are defined in a method, substitute() works as expected:

> setGeneric("fS4", function(x, ...) standardGeneric("fS4"))
> setMethod("fS4", signature("numeric"),
+     function(x, ...) deparse(substitute(x))
+ )
[1] "fS4"
> fS4(iris[,1])
[1] "iris[, 1]"

However, if one adds an extra named argument to the method's definition, substitute() ceases to correctly return the argument as it was passed:

> setMethod("fS4", signature("numeric"),
+     function(x, y, ...) deparse(substitute(x))
+ )
[1] "fS4"
> fS4(iris[,1])
[1] "x"

Any clues on why this happens and, most importantly, how it can be worked around?

Was it helpful?

Solution

Take a look at

showMethods(fS4, includeDef=TRUE)

which shows

Function: fS4 (package .GlobalEnv)
x="numeric"
function (x, ...) 
{
    .local <- function (x, y, ...) 
    deparse(substitute(x))
    .local(x, ...)
}

The way that S4 implements methods with signatures that differ from the generic is by creating a '.local' function with the modified signature, inside a function with the generic signature. substitute then evaluates in an incorrect environment. The underlying problem is not related to S4

> f = function(x) deparse(substitute(x))
> g = function(y) f(y)
> f(1)
[1] "1"
> g(1)
[1] "y"
> h = function(...) f(...)
> h(1)
[1] "1"

and any attempts to evaluate in the the 'right' environment will be thwarted by arbitrary constructs provided by users.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top