From simon.urbanek at r-project.org  Wed Oct 17 04:35:11 2012
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Tue, 16 Oct 2012 22:35:11 -0400
Subject: [Rd] Do *not* pass '...' to NextMethod() - it'll do it for you;
	missing documentation, a bug or just me?
In-Reply-To: <CAFDcVCSak6YS5nKSybAz0TcR+_YQ=NWFwwRjWJXTRE-pSbj8dQ@mail.gmail.com>
References: <CAFDcVCSak6YS5nKSybAz0TcR+_YQ=NWFwwRjWJXTRE-pSbj8dQ@mail.gmail.com>
Message-ID: <7E48E20D-1268-43B7-97C0-0AAED5DA8CB2@r-project.org>


On Oct 16, 2012, at 9:53 PM, Henrik Bengtsson wrote:

> Hi,
> 
> although I've done S3 dispatching for more than a decade now, I think
> I managed to overlook/avoid the following pitfall when using
> NextMethod():
> 
> If you explicitly pass argument '...' to NextMethod(), you will
> effectively pass those argument twice to the "next" method!
> 
> 
> EXAMPLE:
> 
> foo0 <- function(...) UseMethod("foo0");
> foo1 <- function(...) UseMethod("foo1");
> foo2 <- function(...) UseMethod("foo2");
> 
> foo2.A <- foo1.A <- foo0.A <- function(object, a=1, b=2, c=3, d=4, ...) {
>  str(c(list(object=object, a=a, b=b, c=c, d=d), list(...)));
> }
> 
> ## CORRECT: Don't pass arguments '...', but all other
> ## *named* arguments that you wish to be changed in the call.
> foo0.B <- function(object, ..., b=-2) {
>  NextMethod("foo0", object=object, b=b);
> }
> 
> ## INCORRECT: Passing arguments '...' explicitly will *duplicated* them.
> foo1.B <- function(object, ..., b=-2) {
>  NextMethod("foo1", object=object, ..., b=b);
> }
> 
> ## INCORRECT: As an illustration, *triplication* of arguments '...'.
> foo2.B <- function(object, ..., b=-2) {
>  NextMethod("foo2", object=object, ..., ..., b=b);
> }
> 
> objB <- structure(NA, class=c("B", "A"));
> 
> foo0(objB, "???", "!!!");
> ## Gives:
> ## List of 5
> ##  $ object:Classes 'B', 'A'  logi NA
> ##  $ a     : chr "???"
> ##  $ b     : num -2
> ##  $ c     : chr "!!!"
> ##  $ d     : num 4
> 
> foo1(objB, "???", "!!!");
> ## Gives:
> ## List of 6
> ##  $ object:Classes 'B', 'A'  logi NA
> ##  $ a     : chr "???"
> ##  $ b     : num -2
> ##  $ c     : chr "!!!"
> ##  $ d     : chr "???"
> ##  $       : chr "!!!"
> 
> foo2(objB, "???", "!!!");
> ## Gives:
> ## List of 8
> ##  $ object:Classes 'B', 'A'  logi NA
> ##  $ a     : chr "???"
> ##  $ b     : num -2
> ##  $ c     : chr "!!!"
> ##  $ d     : chr "???"
> ##  $       : chr "!!!"
> ##  $       : chr "???"
> ##  $       : chr "!!!"
> 
> This behavior does not seem to be documented (at least not
> explicitly),

I would argue it does:
"Normally ?NextMethod? is used with only one argument, ?generic?, but if further arguments are supplied these modify the call to the next method."
The whole point of NextMethod is that it starts off with the full call *including* ... from the function - by calling NextMethod you are modifying that call, so by adding unnamed arguments you will append them.

And the ... override is explicitly documented: "Any named arguments matched to ?...? are handled specially: they either replace existing arguments of the same name or are appended to the argument list." Try foo1(objB, c="foo", "bla") in your example - it illustrates the difference.

Also why would you pass ... when you don't do it for UseMethod?

Cheers,
Simon



> cf. help("NextMethod", package="base") and Section
> 'NextMethod' in 'R Language Definition'.  I don't have the 'White
> Book', so I don't know what that is saying about this.
> 
> I can reproduce this on Windows, OSX and Linux and various versions of
> R, e.g. R v2.10.0, R v2.15.1 patched, R devel.
> 
> Is this a bug, should it be detected as a user error, should it be
> documented, or is this already old news?
> 
> Thanks,
> 
> Henrik
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> 



[Rd] Do *not* pass '...' to NextMethod() - it'll do it for you; missing documentation, a bug or just me?
Simon Urbanek