On 26/08/10 18.42, Martin Morgan wrote:
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
Oops, right.
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.
I believe that is true. If 'a' is put into the environment two levels
up (using 'browser'), it is found.
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.
But as I understand it, the scoping rules solve such problems and
locate the variable in any environment at a higher level? Replacing
the callGeneric by a direct call of myplus removes the problem, it
seems, though 'a' will still be three levels up.
A simple solution is to provided named arguments to callGeneric, e.g.,
callGeneric(x=x, y=unlist(y), ...).
I don't see how that solves the problem.
- Niels
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
--
Niels Richard Hansen Web: www.math.ku.dk/~richard
Associate Professor Email: niels.r.han...@math.ku.dk
Department of Mathematical Sciences nielsrichardhan...@gmail.com
University of Copenhagen Skype: nielsrichardhansen.dk
Universitetsparken 5 Phone: +45 353 20783 (office)
2100 Copenhagen Ø +45 2859 0765 (mobile)
Denmark
______________________________________________
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.