Thanks Duncan! I filed [1]. I didn't have a clue how to fix it, so I figured, why not ask an LLM [2].
It got the solution quite wrong (unless I'm just not zen enough to understand its wisdom), but it _did_ focus my attention on the right place. I have a patch going through CI at [3] that fixes the bug, I just don't know what knock-on effects it might have. [1] https://bugs.r-project.org/show_bug.cgi?id=18875 [2] https://claude.ai/share/2b702387-6aef-44ee-9e28-17c9096ce8f0 [3] https://github.com/r-devel/r-svn/pull/198 On Tue, Mar 25, 2025 at 3:30 AM Duncan Murdoch <murdoch.dun...@gmail.com> wrote: > > I don't think there's any valid reason for this behaviour, i.e. it's a > bug. For those who haven't read closely, the bug is that in the > `foo(c)` call, within foo.default() the value of `c` is bound to both > x and to the first element of ... . > > The 2012 thread you link to started with a slightly different setup and > arguments were made by Simon that the behaviour is documented, but the > final message in the thread is about the same bug as here. > > I think the bug report 15654 is about the first setup, not the current one. > > So what I'd suggest you do is report this example in a new bug report, > and if you have the energy (seems nobody else does!), track down where > the duplication happens, and include a patch to fix it. > > If you do attempt that, you'll probably learn enough about NextMethod to > decide whether to follow the suggestion in 15654, and could maybe submit > a patch for that, too. > > Duncan Murdoch > > > On 2025-03-25 2:12 a.m., Michael Chirico wrote: > > Consider: > > > > foo <- function(x, y, ...) { > > UseMethod("foo") > > } > > > > foo.default <- function(x, y = 0, ...) { > > cat(sprintf("%s: x=%s, y=%s\n", as.character(match.call()[[1L]]), x, > > y)) > > if (...length()) str(list(...)) > > } > > > > foo.C <- function(x, y = 3, ...) { > > cat(sprintf("%s: x=%s, y=%s\n", as.character(match.call()[[1L]]), x, > > y)) > > if (...length()) str(list(...)) > > NextMethod("foo", x = x, y = y) > > } > > > > c <- structure(class = "C", 1) > > > > # 'x' winds up in ..1 > > foo(c) > > # foo.C: x=1, y=3 > > # foo.default: x=1, y=3 > > # List of 1 > > # $ : 'C' num 1 > > > > # empty ...! > > foo(x=c) > > # foo.C: x=1, y=3 > > # foo.default: x=1, y=3 > > > > # now both x is ..1, y is ..2 > > foo(c, 4) > > # foo.C: x=1, y=4 > > # foo.default: x=1, y=4 > > # List of 2 > > # $ : 'C' num 1 > > # $ : num 4 > > > > # perhaps predictably, ...length()==0 > > foo(x=c, y=4) > > # foo.C: x=1, y=4 > > # foo.default: x=1, y=4 > > > > I've tried re-reading ?NextMethod a few times as well as R-lang [1] & > > can't make heads or tails of this. I've also come across related 2012 > > (!) thread [2] and tangentially-related bug [3]. > > > > Is this intended behavior? If so, might I reiterate Henrik's long-ago > > request for better documentation of how to work around this? > > > > For some added context, where I actually encountered this, my S3 > > method is mainly written to overwrite the defaults of a parent class's > > method. > > > > Mike C > > > > [1] https://cran.r-project.org/doc/manuals/r-devel/R-lang.html#NextMethod > > [2] https://stat.ethz.ch/pipermail/r-devel/2012-October/065016.html > > [3] https://bugs.r-project.org/show_bug.cgi?id=15654 > > > > ______________________________________________ > > R-devel@r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel