Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop = TRUE) {
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a different method.
This seems like a mistake. (That's the polemic.) Or am I missing a better
way? (That's the question.)
David
[R-pkg-devel] slightly polemic question re R CMD check
10 messages · David Hugh-Jones, Gábor Csárdi, Hong Ooi +1 more
You can add the ... argument to chop.default(), and then check that length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones
<davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop = TRUE) {
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a different method.
This seems like a mistake. (That's the polemic.) Or am I missing a better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
You're quite right :-) But I think the polemic still holds, because I have to add manual argument checking to all my methods, which has a cost in lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis.
On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com> wrote:
You can add the ... argument to chop.default(), and then check that length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop = TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a different method.
This seems like a mistake. (That's the polemic.) Or am I missing a better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
You seem to think this is a bad thing. R does encourage lenient argument checking... what rock have you been under for the last 20 years?
On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones <davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because I have to add manual argument checking to all my methods, which has a cost in lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com> wrote:
You can add the ... argument to chop.default(), and then check that length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a different
method.
This seems like a mistake. (That's the polemic.) Or am I missing a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Sent from my phone. Please excuse my brevity.
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions will throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this - which, despite having used R or 17 years, I first discovered today :-). So, it seems the R base developers thought lenient argument checking could be a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as the generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
You seem to think this is a bad thing. R does encourage lenient argument checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because I have to add manual argument checking to all my methods, which has a cost in lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com> wrote:
You can add the ... argument to chop.default(), and then check that length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop =
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a different
method.
This seems like a mistake. (That's the polemic.) Or am I missing a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
-- Sent from my phone. Please excuse my brevity.
R encourages the use of ... particularly in S3 generics, to avoid over-depending on inheritance to enable flexible use of these generics. That is, when you call the generic without knowing which class you are giving it, you cannot specify class-specific arguments. However, some methods have obvious alternative class-specific behaviors that are typically enabled using class-specific arguments (e.g. plot). You cannot support both fully-generic calls and class-specific calls without giving the generic some flexibility that won't get used in some cases.
On March 8, 2020 9:41:51 AM PDT, David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions will throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this - which, despite having used R or 17 years, I first discovered today :-). So, it seems the R base developers thought lenient argument checking could be a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as the generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
You seem to think this is a bad thing. R does encourage lenient
argument
checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because
I
have to add manual argument checking to all my methods, which has a cost
in
lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com>
wrote:
You can add the ... argument to chop.default(), and then check
that
length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a
different
method.
This seems like a mistake. (That's the polemic.) Or am I missing
a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
-- Sent from my phone. Please excuse my brevity.
Sent from my phone. Please excuse my brevity.
... also, the only reason non-generic functions using ellipsis can throw an error when an argument is not used is that they keep passing ... on to functions that recursively encounter fumctions that eventually do not accept an ellipsis argument. If the function calls a generic with an ellipsis argument then we are back into the generic conundrum again and the user will experience the normal function failing to catch unused arguments.
On March 8, 2020 10:14:49 AM PDT, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
R encourages the use of ... particularly in S3 generics, to avoid over-depending on inheritance to enable flexible use of these generics. That is, when you call the generic without knowing which class you are giving it, you cannot specify class-specific arguments. However, some methods have obvious alternative class-specific behaviors that are typically enabled using class-specific arguments (e.g. plot). You cannot support both fully-generic calls and class-specific calls without giving the generic some flexibility that won't get used in some cases. On March 8, 2020 9:41:51 AM PDT, David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions
will
throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this -
which,
despite having used R or 17 years, I first discovered today :-). So,
it
seems the R base developers thought lenient argument checking could be a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as the generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
You seem to think this is a bad thing. R does encourage lenient
argument
checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because
I
have to add manual argument checking to all my methods, which has a cost
in
lines of code. Indeed, few base R methods have chosen to do this.
In
effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com>
wrote:
You can add the ... argument to chop.default(), and then check
that
length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL,
drop
=
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing
R
Extensions? manual. I can fix this by adding a ... argument to chop.default: chop.default <- function (x, breaks, labels, extend = NULL,
drop
=
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a
different
method.
This seems like a mistake. (That's the polemic.) Or am I
missing
a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
-- Sent from my phone. Please excuse my brevity.
Sent from my phone. Please excuse my brevity.
I see the logic, but it seems in practice people often write specific methods with their own specific arguments. (Think of the many plot or print methods for different objects, for example.) Here, enforcing a ... argument does not buy us much. All that we really need is that plot(x) will work for many classes of x. Beyond that, we expect users to read the method-specific documentation. Maybe this is an antipattern. It just seems that S3 methods have turned out to be often used that way. Enforcing ... hasn't stopped it, and causes some awkwardnesses in documentation and error checking. To be clear, I'm not arguing against the generic having flexibility. I'm arguing against enforcing that the method always accepts every argument that the generic could accept.
On Sun, 8 Mar 2020, 17:14 Jeff Newmiller, <jdnewmil at dcn.davis.ca.us> wrote:
R encourages the use of ... particularly in S3 generics, to avoid over-depending on inheritance to enable flexible use of these generics. That is, when you call the generic without knowing which class you are giving it, you cannot specify class-specific arguments. However, some methods have obvious alternative class-specific behaviors that are typically enabled using class-specific arguments (e.g. plot). You cannot support both fully-generic calls and class-specific calls without giving the generic some flexibility that won't get used in some cases. On March 8, 2020 9:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions will throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this - which, despite having used R or 17 years, I first discovered today :-). So, it seems the R base developers thought lenient argument checking could be a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as the generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
You seem to think this is a bad thing. R does encourage lenient
argument
checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because
I
have to add manual argument checking to all my methods, which has a cost
in
lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com>
wrote:
You can add the ... argument to chop.default(), and then check
that
length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a
different
method.
This seems like a mistake. (That's the polemic.) Or am I missing
a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
-- Sent from my phone. Please excuse my brevity.
-- Sent from my phone. Please excuse my brevity.
I tend to agree. Having ... as an argument for a specific method is often unnecessary, and furthermore, can result in errors being hidden. Eg you think you're calling methodname(arg1, arg2="whatever") but you're really calling methodname(arg1, ar2="whatever") and the misspelling isn't picked up, because it gets swallowed by the ... . IMO the whole reason for the current state of affairs is because of a wart in how lm and glm were implemented back in the S-Plus days. A glm object inherits from lm, which doesn't make a lot of sense. It should really be the other way round: the specific case should inherit from the general, so that an lm is a glm, not a glm is an lm. It's way too late to change this now, of course. -----Original Message----- From: R-package-devel <r-package-devel-bounces at r-project.org> On Behalf Of David Hugh-Jones Sent: Sunday, 8 March 2020 6:28 PM To: Jeff Newmiller <jdnewmil at dcn.davis.ca.us> Cc: R package devel <r-package-devel at r-project.org> Subject: [EXTERNAL] Re: [R-pkg-devel] slightly polemic question re R CMD check I see the logic, but it seems in practice people often write specific methods with their own specific arguments. (Think of the many plot or print methods for different objects, for example.) Here, enforcing a ... argument does not buy us much. All that we really need is that plot(x) will work for many classes of x. Beyond that, we expect users to read the method-specific documentation. Maybe this is an antipattern. It just seems that S3 methods have turned out to be often used that way. Enforcing ... hasn't stopped it, and causes some awkwardnesses in documentation and error checking. To be clear, I'm not arguing against the generic having flexibility. I'm arguing against enforcing that the method always accepts every argument that the generic could accept.
On Sun, 8 Mar 2020, 17:14 Jeff Newmiller, <jdnewmil at dcn.davis.ca.us> wrote:
R encourages the use of ... particularly in S3 generics, to avoid over-depending on inheritance to enable flexible use of these generics. That is, when you call the generic without knowing which class you are giving it, you cannot specify class-specific arguments. However, some methods have obvious alternative class-specific behaviors that are typically enabled using class-specific arguments (e.g. plot). You cannot support both fully-generic calls and class-specific calls without giving the generic some flexibility that won't get used in some cases. On March 8, 2020 9:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions will throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this - which, despite having used R or 17 years, I first discovered today :-). So, it seems the R base developers thought lenient argument checking could be a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as the generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:
You seem to think this is a bad thing. R does encourage lenient
argument
checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds, because
I
have to add manual argument checking to all my methods, which has a cost
in
lines of code. Indeed, few base R methods have chosen to do this. In effect, the current setup encourages writing methods with "lenient" argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com>
wrote:
You can add the ... argument to chop.default(), and then check
that
length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the ?Writing R
Extensions? manual.
I can fix this by adding a ... argument to chop.default:
chop.default <- function (x, breaks, labels, extend = NULL, drop
=
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a
different
method.
This seems like a mistake. (That's the polemic.) Or am I missing
a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116746685&sdata=CJ8fTRpoMUxAaJJkI7QSQylGZE3dtd8YLodIZn4C5xA%3D&reserved=0
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116751662&sdata=%2Ba6YarFqDW9nleC7EZjVStMzHwnpQMTTV69CPEEP7eg%3D&reserved=0
-- Sent from my phone. Please excuse my brevity.
-- Sent from my phone. Please excuse my brevity.
______________________________________________ R-package-devel at r-project.org mailing list https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116751662&sdata=%2Ba6YarFqDW9nleC7EZjVStMzHwnpQMTTV69CPEEP7eg%3D&reserved=0
Re backwards specialization... you could also say that a vector is a special kind of matrix... but it most definitely is not that way in R.
On March 9, 2020 9:51:47 AM PDT, Hong Ooi <hongooi at microsoft.com> wrote:
I tend to agree. Having ... as an argument for a specific method is often unnecessary, and furthermore, can result in errors being hidden. Eg you think you're calling methodname(arg1, arg2="whatever") but you're really calling methodname(arg1, ar2="whatever") and the misspelling isn't picked up, because it gets swallowed by the ... . IMO the whole reason for the current state of affairs is because of a wart in how lm and glm were implemented back in the S-Plus days. A glm object inherits from lm, which doesn't make a lot of sense. It should really be the other way round: the specific case should inherit from the general, so that an lm is a glm, not a glm is an lm. It's way too late to change this now, of course. -----Original Message----- From: R-package-devel <r-package-devel-bounces at r-project.org> On Behalf Of David Hugh-Jones Sent: Sunday, 8 March 2020 6:28 PM To: Jeff Newmiller <jdnewmil at dcn.davis.ca.us> Cc: R package devel <r-package-devel at r-project.org> Subject: [EXTERNAL] Re: [R-pkg-devel] slightly polemic question re R CMD check I see the logic, but it seems in practice people often write specific methods with their own specific arguments. (Think of the many plot or print methods for different objects, for example.) Here, enforcing a ... argument does not buy us much. All that we really need is that plot(x) will work for many classes of x. Beyond that, we expect users to read the method-specific documentation. Maybe this is an antipattern. It just seems that S3 methods have turned out to be often used that way. Enforcing ... hasn't stopped it, and causes some awkwardnesses in documentation and error checking. To be clear, I'm not arguing against the generic having flexibility. I'm arguing against enforcing that the method always accepts every argument that the generic could accept. On Sun, 8 Mar 2020, 17:14 Jeff Newmiller, <jdnewmil at dcn.davis.ca.us> wrote:
R encourages the use of ... particularly in S3 generics, to avoid over-depending on inheritance to enable flexible use of these
generics.
That is, when you call the generic without knowing which class you
are
giving it, you cannot specify class-specific arguments. However, some methods have obvious alternative class-specific behaviors that are typically enabled using class-specific arguments (e.g. plot). You
cannot
support both fully-generic calls and class-specific calls without
giving
the generic some flexibility that won't get used in some cases. On March 8, 2020 9:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
Hi Jeff, I wouldn't say R encourages that in general. Non-generic functions
will
throw an error if you use a non-existent argument. And some generic functions check for it: seq(1, 3, blah = 1) [1] 1 2 3 Warning message: In seq.default(1, 3, blah = 1) : extra argument ?blah? will be disregarded In fact there is even a `chkDots()` function to help with this -
which,
despite having used R or 17 years, I first discovered today :-). So,
it
seems the R base developers thought lenient argument checking could
be
a bad thing, presumably because it lets errors go undetected. Maybe chkDots is a reasonable workaround. But I wonder what the rationale is for R CMD check enforcing that methods *must* be as lenient as
the
generic. It seems to lead to a lot of documentation of the form: @param ... Not used. Cheers, David On Sun, 8 Mar 2020 at 16:24, Jeff Newmiller
<jdnewmil at dcn.davis.ca.us>
wrote:
You seem to think this is a bad thing. R does encourage lenient
argument
checking... what rock have you been under for the last 20 years? On March 8, 2020 5:41:51 AM PDT, David Hugh-Jones < davidhughjones at gmail.com> wrote:
You're quite right :-) But I think the polemic still holds,
because
I
have to add manual argument checking to all my methods, which has a
cost
in
lines of code. Indeed, few base R methods have chosen to do this.
In
effect, the current setup encourages writing methods with
"lenient"
argument specifications. Thank you for the suggestion about ellipsis. On Sun, 8 Mar 2020, 11:04 G?bor Cs?rdi, <csardi.gabor at gmail.com>
wrote:
You can add the ... argument to chop.default(), and then check
that
length(list(...)) is zero. Also, you might be interested in the ellipsis package. Gabor On Sun, Mar 8, 2020 at 10:56 AM David Hugh-Jones <davidhughjones at gmail.com> wrote:
Hi all,
My package defines the following method and generic:
chop <- function (x, ...) UseMethod("chop")
chop.default <- function (x, breaks, labels, extend = NULL,
drop
=
TRUE)
{
... }
R CMD check then gives a warning:
W checking S3 generic/method consistency (695ms)
chop:
function(x, ...)
chop.default:
function(x, breaks, labels, extend, drop)
See section ?Generic functions and methods? in the
?Writing R
Extensions? manual. I can fix this by adding a ... argument to chop.default: chop.default <- function (x, breaks, labels, extend = NULL,
drop
=
TRUE, ...)
But that makes the code less robust because e.g.
chop(x, Breaks = 1:3)
will no longer throw an error from the misspelled argument.
Or I can write:
chop(x, breaks, labels, extend, drop) UseMethod("chop")
but this means I cannot use a different interface for a
different
method.
This seems like a mistake. (That's the polemic.) Or am I
missing
a
better
way? (That's the question.)
David
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116746685&sdata=CJ8fTRpoMUxAaJJkI7QSQylGZE3dtd8YLodIZn4C5xA%3D&reserved=0
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116751662&sdata=%2Ba6YarFqDW9nleC7EZjVStMzHwnpQMTTV69CPEEP7eg%3D&reserved=0
-- Sent from my phone. Please excuse my brevity.
-- Sent from my phone. Please excuse my brevity.
[[alternative HTML version deleted]]
______________________________________________ R-package-devel at r-project.org mailing list https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstat.ethz.ch%2Fmailman%2Flistinfo%2Fr-package-devel&data=02%7C01%7Chongooi%40microsoft.com%7C0ad9cebc4ce24e7d50e508d7c3b006de%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637193033116751662&sdata=%2Ba6YarFqDW9nleC7EZjVStMzHwnpQMTTV69CPEEP7eg%3D&reserved=0
Sent from my phone. Please excuse my brevity.