On 8/26/2010 8:43 AM, Niels Richard Hansen wrote:
setGeneric("myplus",function(x,y,...) standardGeneric("myplus"))
setMethod("myplus",c(x="numeric",y="numeric"),
          function(x,y,z=0) x+y+z
          )
setMethod("myplus",c(x="numeric",y="list"),
          function(x,y,...) callGeneric(x,unlist(y),...)
          )

myplus(1,1)   ## 2; OK
myplus(1,1,1) ## 3; OK

myplus(1,list(1)) ## 2; OK
myplus(1,list(1),z=1) ## 3; OK

a.c1 <- 1
myplus(1,list(1),z=a.c1) ## 3; OK

test <- function(x,y) {
  a.c <- 1    ## Problem occurs when using '.' in variable name
  myplus(a,y,z=a.c)
}

test(1,list(1)) ## error
test(1,1)  ## 3; OK

I get an error in both instances, because in fact there is no variable 'a' defined (anywhere) in the session. I do get your results if I define a global variable a <- 2

The reason for the original problem can be seen by looking at how the methods are implemented (I added parentheses in the setMethod calls for clarity)

> showMethods(myplus, includeDef=TRUE)
Function: myplus (package .GlobalEnv)
x="numeric", y="list"
function (x, y, ...)
{
    callGeneric(x, unlist(y), ...)
}


x="numeric", y="numeric"
function (x, y, ...)
{
    .local <- function (x, y, z = 0)
    {
        x + y + z
    }
    .local(x, y, ...)
}

and in particular the c("numeric", "numeric") method has an extra argument z, and so has a nested .local function. This is how the methods package deals with method signatures that differ from the generic.

I think, roughly, that when c("numeric", "numeric") tries finally to resolve it's argument 'x', it looks for a variable 'a' in the environment two levels up (method --> generic) from where it is being resolved. This is fine if the method has no .local environment (e.g., if c("numeric", "numeric") where defined as function(x, y, ...) { x +y }). I think that there is no general solution to this; the user could callGeneric or evaluate symbols from arbitrarily nested functions within either the calling or called methods themselves, and could arrive at a particular method through callGeneric or other routes (e.g., callNextMethod) that are not consistent in terms of the implied frame of evaluation. I could be mistaken.

A simple solution is to provided named arguments to callGeneric, e.g., callGeneric(x=x, y=unlist(y), ...).

These issues are likely to cause problems for eval / substitute expressions like the one posted by Joris yesterday, where there are implicit assumptions about the environment in which the experession is being evaluated.

Martin

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to