Hi,
Any idea why S4 doesn't allow slots of type "double"?
> setClass("A", representation(a="double"))
Error in makePrototypeFromClassDef(properties, ClassDef, immediate, where) :
in making the prototype for class "A" elements of the prototype failed to
match the corresponding slot class: a (class ?double? )
"numeric", "integer", "character", "complex", "raw", etc... they all work
but "double" doesn't. Any reason for this strange exception?
Thanks!
H.
slots of type "double"
9 messages · Hervé Pagès, Simon Urbanek, John Chambers +2 more
On Nov 13, 2007, at 3:36 AM, hpages at fhcrc.org wrote:
Any idea why S4 doesn't allow slots of type "double"?
Type (as in storage type and "double" is a storage type) has nothing to do with classes. You cannot create slots for types, only for classes.
setClass("A", representation(a="double"))
Error in makePrototypeFromClassDef(properties, ClassDef, immediate, where) : in making the prototype for class "A" elements of the prototype failed to match the corresponding slot class: a (class ?double? ) "numeric", "integer", "character", "complex", "raw", etc... they all work but "double" doesn't. Any reason for this strange exception?
AFAICS there is no way to create an object of the class "double" (save
for 'faking' it by creating an informal S3 object), so such definition
is useless. And given this fact, even the internal code is unable to
create it, so it doesn't match the signature. Note:
> a=new("double")
> class(a)
[1] "numeric"
> is(a,"double")
[1] FALSE
I think it comes from the fact that there is an S4 definition for the
class "double" which is not valid. That is probably a bug and the
class definition should be removed.
Cheers,
Simon
On Tue, 13 Nov 2007, Simon Urbanek wrote:
On Nov 13, 2007, at 3:36 AM, hpages at fhcrc.org wrote:
Any idea why S4 doesn't allow slots of type "double"?
Type (as in storage type and "double" is a storage type) has nothing to do with classes. You cannot create slots for types, only for classes.
Unfortunately not in the world of the 'methods' package (which seems to differ here from the Green Book and S-PLUS). There's a basic class "double" (and also "single") defined in BasicClasses.R. It say:
getClass("double")
No Slots, prototype of class "numeric" Extends: "vector", "numeric"
getClass("numeric")
No Slots, prototype of class "numeric" Extends: "vector" Known Subclasses: "double", "integer" So it is an otherwise unspecified subclass of "numeric". Now when you do
a <- new("numeric", pi)
a
[1] 3.141593
class(a)
[1] "numeric" you are in fact calling class() on a REALSXP, and that is set up to report "numeric" (the implicit class comes from mode not type, except for "integer"). Anther area of confusion is that as.numeric, as.double and as.real are three names for the same thing, but is.numeric and is.double are not the same. So we end up with
x <- 1:3 is.numeric(x)
[1] TRUE
identical(x, as.numeric(x))
[1] FALSE
x <- pi is.numeric(x)
[1] TRUE
identical(x, as.numeric(x))
[1] TRUE Basically I think class() is wrong (it should use "double"), but it was not my choice and it was presumably done to agree with the Green Book. I agree that it would be best to remove the "double" and "single" S4 classes. At least in the version of S-PLUS I have left, "double" does not exist -- "single" does but is a distinct storage type.
setClass("A", representation(a="double"))
Error in makePrototypeFromClassDef(properties, ClassDef, immediate, where) : in making the prototype for class "A" elements of the prototype failed to match the corresponding slot class: a (class ?double? ) "numeric", "integer", "character", "complex", "raw", etc... they all work but "double" doesn't. Any reason for this strange exception?
AFAICS there is no way to create an object of the class "double" (save for 'faking' it by creating an informal S3 object), so such definition is useless. And given this fact, even the internal code is unable to create it, so it doesn't match the signature. Note:
a=new("double")
class(a)
[1] "numeric"
is(a,"double")
[1] FALSE I think it comes from the fact that there is an S4 definition for the class "double" which is not valid. That is probably a bug and the class definition should be removed. Cheers, Simon
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
An embedded and charset-unspecified text was scrubbed... Name: not available Url: https://stat.ethz.ch/pipermail/r-devel/attachments/20071113/f13be655/attachment.pl
On Tue, 13 Nov 2007, John Chambers wrote:
What's the proposal here? To eliminate "double" as a class? No objection
Eliminate "double" and "single".
from this corner. As I remember, it was put in early in the implementation of methods, when I was confused about what R intended in this area (well, I'm not totally unconfused even now). If this is the proposal, we could implement it in r-devel and see if there are complaints.
I was going to propose so after running some tests over CRAN/BioC (which will take a few hours). Brian
Prof Brian Ripley wrote:
On Tue, 13 Nov 2007, Simon Urbanek wrote:
On Nov 13, 2007, at 3:36 AM, hpages at fhcrc.org wrote:
Any idea why S4 doesn't allow slots of type "double"?
Type (as in storage type and "double" is a storage type) has nothing to do with classes. You cannot create slots for types, only for classes.
Unfortunately not in the world of the 'methods' package (which seems to differ here from the Green Book and S-PLUS). There's a basic class "double" (and also "single") defined in BasicClasses.R. It say:
getClass("double")
No Slots, prototype of class "numeric" Extends: "vector", "numeric"
getClass("numeric")
No Slots, prototype of class "numeric" Extends: "vector" Known Subclasses: "double", "integer" So it is an otherwise unspecified subclass of "numeric". Now when you do
a <- new("numeric", pi)
a
[1] 3.141593
class(a)
[1] "numeric" you are in fact calling class() on a REALSXP, and that is set up to report "numeric" (the implicit class comes from mode not type, except for "integer"). Anther area of confusion is that as.numeric, as.double and as.real are three names for the same thing, but is.numeric and is.double are not the same. So we end up with
x <- 1:3 is.numeric(x)
[1] TRUE
identical(x, as.numeric(x))
[1] FALSE
x <- pi is.numeric(x)
[1] TRUE
identical(x, as.numeric(x))
[1] TRUE Basically I think class() is wrong (it should use "double"), but it was not my choice and it was presumably done to agree with the Green Book. I agree that it would be best to remove the "double" and "single" S4 classes. At least in the version of S-PLUS I have left, "double" does not exist -- "single" does but is a distinct storage type.
setClass("A", representation(a="double"))
Error in makePrototypeFromClassDef(properties, ClassDef, immediate, where) : in making the prototype for class "A" elements of the prototype failed to match the corresponding slot class: a (class ?double? ) "numeric", "integer", "character", "complex", "raw", etc... they all work but "double" doesn't. Any reason for this strange exception?
AFAICS there is no way to create an object of the class "double" (save for 'faking' it by creating an informal S3 object), so such definition is useless. And given this fact, even the internal code is unable to create it, so it doesn't match the signature. Note:
a=new("double")
class(a)
[1] "numeric"
is(a,"double")
[1] FALSE I think it comes from the fact that there is an S4 definition for the class "double" which is not valid. That is probably a bug and the class definition should be removed. Cheers, Simon
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On Tue, 13 Nov 2007, Prof Brian Ripley wrote:
On Tue, 13 Nov 2007, John Chambers wrote:
What's the proposal here? To eliminate "double" as a class? No objection
Eliminate "double" and "single".
from this corner. As I remember, it was put in early in the implementation of methods, when I was confused about what R intended in this area (well, I'm not totally unconfused even now). If this is the proposal, we could implement it in r-devel and see if there are complaints.
I was going to propose so after running some tests over CRAN/BioC (which will take a few hours).
Which showed up problems in packages Matrix and matlab.
Matrix clearly has a different view of these classes:
## "atomic vectors" (-> ?is.atomic ) --
## --------------- those that we want to convert from old-style "matrix"
setClassUnion("atomicVector", ## numeric = {integer, double} but all 3
should *directly* be atomic
members = c("logical", "integer", "double", "numeric",
"complex", "raw", "character"))
If I remove "double" there, I get an error in an example:
stopifnot(is(scm, "sparseVector"),
+ identical(cm, as.numeric(scm)))
Error in as(x at x, mode) :
no method or default for coercing "numeric" to "double"
and looking at the code suggests that "double" is used as the class name
in several places.
Package matlab is simpler: test mkconstarray.R fails at
> test.mkconstarray(list(class.type = "double", value = pi, size = 4),
rep(pi, 4))
Error in as(value, match.arg(class.type)) :
no method or default for coercing "numeric" to "double"
and needs the author to rectify his confusion between "class" and "type".
I'd like to give the Matrix authors a chance to look into this before
making the change. Loking at the packages has reinforced my impression
that having "double" as an S4 class is only adding confusion, so the
change is desirable.
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On Wed, November 14, 2007 09:09, Prof Brian Ripley wrote:
On Tue, 13 Nov 2007, Prof Brian Ripley wrote:
On Tue, 13 Nov 2007, John Chambers wrote:
What's the proposal here? To eliminate "double" as a class? No objection
Eliminate "double" and "single".
from this corner. As I remember, it was put in early in the implementation of methods, when I was confused about what R intended in this area (well, I'm not totally unconfused even now). If this is the proposal, we could implement it in r-devel and see if there are complaints.
I was going to propose so after running some tests over CRAN/BioC (which will take a few hours).
Which showed up problems in packages Matrix and matlab.
Matrix clearly has a different view of these classes:
## "atomic vectors" (-> ?is.atomic ) --
## --------------- those that we want to convert from old-style "matrix"
setClassUnion("atomicVector", ## numeric = {integer, double} but all 3
should *directly* be atomic
members = c("logical", "integer", "double", "numeric",
"complex", "raw", "character"))
If I remove "double" there, I get an error in an example:
stopifnot(is(scm, "sparseVector"),
+ identical(cm, as.numeric(scm))) Error in as(x at x, mode) : no method or default for coercing "numeric" to "double" and looking at the code suggests that "double" is used as the class name in several places. Package matlab is simpler: test mkconstarray.R fails at
> test.mkconstarray(list(class.type = "double", value = pi, size = 4),
rep(pi, 4))
Error in as(value, match.arg(class.type)) :
no method or default for coercing "numeric" to "double"
and needs the author to rectify his confusion between "class" and "type".
I'd like to give the Matrix authors a chance to look into this before
making the change. Loking at the packages has reinforced my impression
that having "double" as an S4 class is only adding confusion, so the
change is desirable.
I think (without having had time to check all implications) that I agree quite a bit. I don't think that I was not partly confused about things, either as they were in Matrix when I "entered the project" or as they turned out to work or fail, when we started to use those class definitions quite a few R versions back, when also "methods" / "base" may have behaved a bit differently than now. I must admit that I did not program according to documented behavior, but rather to work behavior :-) ;-) I'm very busy the rest of this week, in out'of'town meetings, so won't be able to comment much more. Martin
still found a bit time for more remarks.
"MM" == Martin M?chler <maechler at stat.math.ethz.ch>
on Wed, 14 Nov 2007 14:23:12 +0100 (CET) writes:
MM> On Wed, November 14, 2007 09:09, Prof Brian Ripley
MM> wrote:
>> On Tue, 13 Nov 2007, Prof Brian Ripley wrote:
>>
>>> On Tue, 13 Nov 2007, John Chambers wrote:
>>>
>>>> What's the proposal here? To eliminate "double" as a
>>>> class? No objection
>>>
>>> Eliminate "double" and "single".
>>>
>>>> from this corner. As I remember, it was put in early
>>>> in the implementation of methods, when I was confused
>>>> about what R intended in this area (well, I'm not
>>>> totally unconfused even now).
>>>>
>>>> If this is the proposal, we could implement it in
>>>> r-devel and see if there are complaints.
>>>
>>> I was going to propose so after running some tests over
>>> CRAN/BioC (which will take a few hours).
>>
>> Which showed up problems in packages Matrix and matlab.
>> Matrix clearly has a different view of these classes:
>>
>> ## "atomic vectors" (-> ?is.atomic ) -- ##
>> --------------- those that we want to convert from
>> old-style "matrix" setClassUnion("atomicVector", ##
>> numeric = {integer, double} but all 3 should *directly*
>> be atomic members = c("logical", "integer", "double",
>> "numeric", "complex", "raw", "character"))
>>
>> If I remove "double" there, I get an error in an example:
>>
>>> stopifnot(is(scm, "sparseVector"),
>> + identical(cm, as.numeric(scm))) Error in as(x at x, mode)
>> : no method or default for coercing "numeric" to "double"
>>
>> and looking at the code suggests that "double" is used as
>> the class name in several places.
yes.
As you mention and I had in the comment above,
I've worked from the premise of something like a class union of
numeric = {integer, double}
-- which corresponds to S3's is.numeric() which we all know
differs from the semantic of as.numeric()
and now know why I had done so {empty lines deleted}:
> showClass("numeric")
No Slots, prototype of class "numeric"
Extends: "vector"
Known Subclasses: "double", "integer"
> showClass("double")
No Slots, prototype of class "numeric"
Extends: "vector", "numeric"
> showClass("integer")
No Slots, prototype of class "integer"
Extends: "vector", "numeric"
which you partially also mentioned in your initial posting.
As a 2nd thought I wonder if we should not keep this current
scheme and fix its behavior where needed (the problem the OP had):
The notion of numeric := union(double, integer)
does now appeal to me again;
in particular since eliminating "double" in the S4 world will
not eliminate it from other places, and the basic problem of
is.numeric / as.numeric inconsistency is - I think - not
something we'd want to eliminate, just because it would break too
much existing code (and books on S and R).
Of course I may have overlooked other reasonings;
as mentioned, I'm quite a bit time limited at the moment.
Martin
[....]
>> I'd like to give the Matrix authors a chance to look into
>> this before making the change.
Thanks, indeed!
>> Loking at the packages has reinforced my impression that
>> having "double" as an S4 class is only adding confusion,
>> so the change is desirable.
well or maybe it's just the lack of comprehensive documentation
of S4 classes as in 'methods' in R -- where I think JMC did want
to do a few things slightly differently than they are in S-PLUS..
MM> I think (without having had time to check all
MM> implications) that I agree quite a bit. I don't think
MM> that I was not partly confused about things, either as
MM> they were in Matrix when I "entered the project" or as
MM> they turned out to work or fail, when we started to use
MM> those class definitions quite a few R versions back,
MM> when also "methods" / "base" may have behaved a bit
MM> differently than now. I must admit that I did not
MM> program according to documented behavior, but rather to
MM> work behavior :-) ;-)
MM> I'm very busy the rest of this week, in out'of'town
MM> meetings, so won't be able to comment much more. Martin
In-line omments near the end:
On Wed, 14 Nov 2007, Martin Maechler wrote:
still found a bit time for more remarks.
"MM" == Martin M?chler <maechler at stat.math.ethz.ch>
on Wed, 14 Nov 2007 14:23:12 +0100 (CET) writes:
MM> On Wed, November 14, 2007 09:09, Prof Brian Ripley MM> wrote:
>> On Tue, 13 Nov 2007, Prof Brian Ripley wrote: >>
>>> On Tue, 13 Nov 2007, John Chambers wrote: >>>
>>>> What's the proposal here? To eliminate "double" as a >>>> class? No objection
>>> >>> Eliminate "double" and "single". >>>
>>>> from this corner. As I remember, it was put in early >>>> in the implementation of methods, when I was confused >>>> about what R intended in this area (well, I'm not >>>> totally unconfused even now). >>>> >>>> If this is the proposal, we could implement it in >>>> r-devel and see if there are complaints.
>>> >>> I was going to propose so after running some tests over >>> CRAN/BioC (which will take a few hours).
>> >> Which showed up problems in packages Matrix and matlab.
>> Matrix clearly has a different view of these classes:
>>
>> ## "atomic vectors" (-> ?is.atomic ) -- ##
>> --------------- those that we want to convert from
>> old-style "matrix" setClassUnion("atomicVector", ##
>> numeric = {integer, double} but all 3 should *directly*
>> be atomic members = c("logical", "integer", "double",
>> "numeric", "complex", "raw", "character"))
>>
>> If I remove "double" there, I get an error in an example:
>>
>>> stopifnot(is(scm, "sparseVector"),
>> + identical(cm, as.numeric(scm))) Error in as(x at x, mode) >> : no method or default for coercing "numeric" to "double" >> >> and looking at the code suggests that "double" is used as >> the class name in several places.
yes.
As you mention and I had in the comment above,
I've worked from the premise of something like a class union of
numeric = {integer, double}
-- which corresponds to S3's is.numeric() which we all know
differs from the semantic of as.numeric()
(It predates S3 classes, being in the Blue Book. And what as.numeric does in R differs from the Blue Book description, although for a long time the R help gave the BB version. But S also differs, at least in recent years.)
and now know why I had done so {empty lines deleted}:
> showClass("numeric")
No Slots, prototype of class "numeric" Extends: "vector" Known Subclasses: "double", "integer"
> showClass("double")
No Slots, prototype of class "numeric" Extends: "vector", "numeric"
> showClass("integer")
No Slots, prototype of class "integer" Extends: "vector", "numeric" which you partially also mentioned in your initial posting.
(I posted output from getClass, as showClass is not in the Green Book, although I actually used showClass first.)
As a 2nd thought I wonder if we should not keep this current scheme and fix its behavior where needed (the problem the OP had): The notion of numeric := union(double, integer) does now appeal to me again;
I don't believe we can get from here to there without massive upheaval. "numeric" is not a virtual class, and making "double" the basic class and "numeric" a virtual one would break tons of code (and writeups).
in particular since eliminating "double" in the S4 world will not eliminate it from other places, and the basic problem of is.numeric / as.numeric inconsistency is - I think - not something we'd want to eliminate, just because it would break too much existing code (and books on S and R).
(I do wonder if any of those books do get to that level of detail, and if they do what system they describe, given the divergence from the Blue Book. I checked that the VR ones do not. I tend to agree with the BB comment that the storage type only matters in external interfaces, although that perhaps undervalues +/-Inf which may not have been available back then.) I may be wrong, but I believe class "double" does not exist in the (strict sense) S4 world: it was certainly not in S-PLUS 6.2. With a clean-sheet design we might well do things differently, and I think it would be possible for Matrix to make use of a class union of "numeric" and "integer". But the name "numeric" is already taken and we are going to have to live with three names [*] for the same concept, and setting S3 methods on as.double and S4 ones on as.numeric (because it would be too painful to change either). Brian [*] numeric, double, real. My proposal to remove 'real' met with objections.
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595