R-alpha: UseMethod and ...

Thomas Lumley (thomas@biostat.washington.edu)
Thu, 19 Sep 1996 11:07:40 -0700 (PDT)


Date: Thu, 19 Sep 1996 11:07:40 -0700 (PDT)
From: Thomas Lumley <thomas@biostat.washington.edu>
To: r-testers <r-testers@stat.math.ethz.ch>
Subject: R-alpha: UseMethod and ...
In-Reply-To: <Pine.SUN.3.91.960918130618.13750F-100000@babcomm>


There is a problem when a method needs to have an argument available to 
it but also needs to pass the argument to the next method.  Once an 
argument is given a formal name it is no longer possible to pass it down 
to another method without knowing the formal argument name in that method.

An artificially simple axample (there are real examples in the survival4 
library)

Suppose a generic function foo() has methods for classes "bar" and "baz", 
with S code as follows:

foo<-function(x,...) UseMethod("foo",x,...)
foo.bar <-function(x,z,...) NextMethod("foo")
foo.baz <-function(p,q,r) {print(p);print(q);print(r)}
foo(x,1,2)

In S this works. Note that foo.bar() defines the second argument z. In a 
real example it would do something with z.

While NextMethod doesn't work exactly the same way as in S, there seem to be
five basic possibilities for foo.bar()

foo.bar <-function(x,z,...) NextMethod("foo")
foo.bar <-function(x,z,...) NextMethod("foo",x)
foo.bar <-function(x,z,...) NextMethod("foo",x,...)
foo.bar <-function(x,z,...) NextMethod("foo",x,z)
foo.bar <-function(x,z,...) NextMethod("foo",x,z,...)

None of these works. They give, respectively:

Error: get: invalid first argument

[1] 1
attr(,"class")
[1] "bar" "baz"
[1] 2
Error: Argument "r" is missing, with no default

[1] 1
attr(,"class")
[1] "bar" "baz"
[1] 2
[1] 2

[1] 1
attr(,"class")
[1] "bar" "baz"
[1] 2
[1] 1


Error in foo.baz(x, ..., 1, 2) : unused argument to function

Note that the third one *appears* to work but gives the wrong answer.  
The fourth one also appears to work, but gets the arguments the wrong way 
around.

If foo.bar() didn't use z then the correct version is 
foo.bar <-function(x,...) NextMethod("foo",x)

If we knew that the second argument of the next method was called q, this
works
foo.bar <-function(x,z,...) NextMethod("foo",x,q=z)

In general, though, we don't know what names are going to be used by 
other methods.


Note also that this sort of definition is used by the primitive "[" 
operator, which handles standard cases itself and passes methods to the
appropriate function. This may possibly explain why "[" methods don't get
missing arguments presented properly. For example, the function that
caused my initial question about missingness is

"[.Surv"<-function (x, i, j, drop = F) 
{
        temp <- class(x)
        type <- attr(x, "type")
        class(x) <- NULL
        attr(x, "type") <- NULL
        if (missing(j)) {
                x <- x[i, , drop = drop]
                class(x) <- temp
                attr(x, "type") <- type
                x
        }
        else NextMethod("[")
}

The test for missing j does not work in R, although it does in S.


thomas lumley
U Washington
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
r-testers mailing list -- To (un)subscribe, send
subscribe	or	unsubscribe
(in the "body", not the subject !)  To: r-testers-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-