Martin Maechler
2015-Dec-11 09:25 UTC
[Rd] For integer vectors, `as(x, "numeric")` has no effect.
>>>>> Martin Maechler <maechler at stat.math.ethz.ch> >>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes:>>>>> John Chambers <jmc at r-project.org> >>>>> on Mon, 7 Dec 2015 16:05:59 -0800 writes:>> We do need an explicit method here, I think. >> The issue is that as() uses methods for the generic function coerce() but cannot use inheritance in the usual way (if it did, you would be immediately back with no change, since "integer" inherits from "numeric"). >> Copying in the general method for coercing to "numeric" as an explicit method for "integer" gives the expected result: >>> setMethod("coerce", c("integer", "numeric"), getMethod("coerce", c("ANY", "numeric"))) >> [1] "coerce" >>> typeof(as(1L, "numeric")) >> [1] "double" >> Seems like a reasonable addition to the code, unless someone sees a problem. >> John > I guess that that some package checks (in CRAN + Bioc + ... - > land) will break, > but I still think we should add such a coercion to R. > Martin Hmm... I've tried to add the above to R and do notice that there are consequences that may be larger than anticipated: Here is example code: myN <- setClass("myN", contains="numeric") myNid <- setClass("myNid", contains="numeric", representation(id="character")) NN <- setClass("NN", representation(x="numeric")) (m1 <- myN (1:3)) (m2 <- myNid(1:3, id = "i3")) tools::assertError(NN (1:3))# in all R versions ## # current R | new R ## # -----------|---------- class(getDataPart(m1)) # integer | numeric class(getDataPart(m2)) # integer | numeric In other words, with the above setting, the traditional gentleperson's agreement in S and R, __ "numeric" sometimes conveniently means "integer" or "double" __ will be slightly less often used ... which of course may be a very good thing. However, it breaks strict back compatibility also in cases where the previous behavior may have been preferable: After all integer vectors need only have the space of doubles. Shall we still go ahead and do apply this change to R-devel and then all package others will be willing to update where necessary? As this may affect the many hundreds of bioconductor packages using S4 classes, I am -- exceptionally -- cross posting to the bioc-devel list. Martin Maechler >> On Dec 7, 2015, at 3:37 PM, Benjamin Tyner <btyner at gmail.com> wrote: >>> Perhaps it is not that surprising, given that >>> >>> > mode(1L) >>> [1] "numeric" >>> >>> and >>> >>> > is.numeric(1L) >>> [1] TRUE >>> >>> On the other hand, this is curious, to say the least: >>> >>> > is.double(as(1L, "double")) >>> [1] FALSE >>> >>>> Here's the surprising behavior: >>>> >>>> x <- 1L >>>> xx <- as(x, "numeric") >>>> class(xx) >>>> ## [1] "integer" >>>> >>>> It occurs because the call to `as(x, "numeric")` dispatches the coerce >>>> S4 method for the signature `c("integer", "numeric")`, whose body is >>>> copied in below. >>>> >>>> function (from, to = "numeric", strict = TRUE) >>>> if (strict) { >>>> class(from) <- "numeric" >>>> from >>>> } else from >>>> >>>> This in turn does nothing, even when strict=TRUE, because that >>>> assignment to class "numeric" has no effect: >>>> >>>> x <- 10L >>>> class(x) <- "numeric" >>>> class(x) >>>> [1] "integer" >>>> >>>> Is this the desired behavior for `as(x, "numeric")`? >>> >>> ______________________________________________ >>> R-devel at r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
John Chambers
2015-Dec-11 18:11 UTC
[Rd] For integer vectors, `as(x, "numeric")` has no effect.
Somehow, the most obvious fixes are always back-incompatible these days. The example intrigued me, so I looked into it a bit (should have been doing something else, but ....) You're right that this is the proverbial thin-edge-of-the-wedge. The problem is in setDataPart(), which will be called whenever a class extends one of the vector types. It does as(value, dataClass) The key point is that the third argument to as(), strict=TRUE by default. So, yes, the change will cause all integer vectors to become double when the class extends "numeric". Generally, strict=TRUE makes sense here and of course changing THAT would open up yet more incompatibilities. For back compatibility, one would have to have some special code in setDataPart() for the case of integer/numeric. John (Historically, the original sin was probably not making a distinction between "numeric" as a virtual class and "double" as a type/class.) On Dec 11, 2015, at 1:25 AM, Martin Maechler <maechler at stat.math.ethz.ch> wrote:>>>>>> Martin Maechler <maechler at stat.math.ethz.ch> >>>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes: > >>>>>> John Chambers <jmc at r-project.org> >>>>>> on Mon, 7 Dec 2015 16:05:59 -0800 writes: > >>> We do need an explicit method here, I think. >>> The issue is that as() uses methods for the generic function coerce() but cannot use inheritance in the usual way (if it did, you would be immediately back with no change, since "integer" inherits from "numeric"). > >>> Copying in the general method for coercing to "numeric" as an explicit method for "integer" gives the expected result: > >>>> setMethod("coerce", c("integer", "numeric"), getMethod("coerce", c("ANY", "numeric"))) >>> [1] "coerce" >>>> typeof(as(1L, "numeric")) >>> [1] "double" > >>> Seems like a reasonable addition to the code, unless someone sees a problem. >>> John > >> I guess that that some package checks (in CRAN + Bioc + ... - >> land) will break, >> but I still think we should add such a coercion to R. > >> Martin > > Hmm... I've tried to add the above to R > and do notice that there are consequences that may be larger than > anticipated: > > Here is example code: > > myN <- setClass("myN", contains="numeric") > myNid <- setClass("myNid", contains="numeric", representation(id="character")) > NN <- setClass("NN", representation(x="numeric")) > > (m1 <- myN (1:3)) > (m2 <- myNid(1:3, id = "i3")) > tools::assertError(NN (1:3))# in all R versions > > ## # current R | new R > ## # -----------|---------- > class(getDataPart(m1)) # integer | numeric > class(getDataPart(m2)) # integer | numeric > > > In other words, with the above setting, the traditional > gentleperson's agreement in S and R, > > __ "numeric" sometimes conveniently means "integer" or "double" __ > > will be slightly less often used ... which of course may be a > very good thing. > > However, it breaks strict back compatibility also in cases where > the previous behavior may have been preferable: > After all integer vectors need only have the space of doubles. > > Shall we still go ahead and do apply this change to R-devel > and then all package others will be willing to update where necessary? > > As this may affect the many hundreds of bioconductor packages > using S4 classes, I am -- exceptionally -- cross posting to the > bioc-devel list. > > Martin Maechler > > >>> On Dec 7, 2015, at 3:37 PM, Benjamin Tyner <btyner at gmail.com> wrote: > >>>> Perhaps it is not that surprising, given that >>>> >>>>> mode(1L) >>>> [1] "numeric" >>>> >>>> and >>>> >>>>> is.numeric(1L) >>>> [1] TRUE >>>> >>>> On the other hand, this is curious, to say the least: >>>> >>>>> is.double(as(1L, "double")) >>>> [1] FALSE >>>> >>>>> Here's the surprising behavior: >>>>> >>>>> x <- 1L >>>>> xx <- as(x, "numeric") >>>>> class(xx) >>>>> ## [1] "integer" >>>>> >>>>> It occurs because the call to `as(x, "numeric")` dispatches the coerce >>>>> S4 method for the signature `c("integer", "numeric")`, whose body is >>>>> copied in below. >>>>> >>>>> function (from, to = "numeric", strict = TRUE) >>>>> if (strict) { >>>>> class(from) <- "numeric" >>>>> from >>>>> } else from >>>>> >>>>> This in turn does nothing, even when strict=TRUE, because that >>>>> assignment to class "numeric" has no effect: >>>>> >>>>> x <- 10L >>>>> class(x) <- "numeric" >>>>> class(x) >>>>> [1] "integer" >>>>> >>>>> Is this the desired behavior for `as(x, "numeric")`? >>>> >>>> ______________________________________________ >>>> R-devel at r-project.org mailing list >>>> https://stat.ethz.ch/mailman/listinfo/r-devel > >>> ______________________________________________ >>> R-devel at r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel > >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel[[alternative HTML version deleted]]
Morgan, Martin
2015-Dec-11 22:10 UTC
[Rd] For integer vectors, `as(x, "numeric")` has no effect.
From the Bioconductor side of things, the general feeling is that this is a step in the right direction and worth the broken packages. Martin Morgan ________________________________________ From: R-devel [r-devel-bounces at r-project.org] on behalf of Martin Maechler [maechler at stat.math.ethz.ch] Sent: Friday, December 11, 2015 4:25 AM To: John Chambers; r-devel at r-project.org; bioc-devel list; Benjamin Tyner Cc: Martin Maechler Subject: Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.>>>>> Martin Maechler <maechler at stat.math.ethz.ch> >>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes:>>>>> John Chambers <jmc at r-project.org> >>>>> on Mon, 7 Dec 2015 16:05:59 -0800 writes:>> We do need an explicit method here, I think. >> The issue is that as() uses methods for the generic function coerce() but cannot use inheritance in the usual way (if it did, you would be immediately back with no change, since "integer" inherits from "numeric"). >> Copying in the general method for coercing to "numeric" as an explicit method for "integer" gives the expected result: >>> setMethod("coerce", c("integer", "numeric"), getMethod("coerce", c("ANY", "numeric"))) >> [1] "coerce" >>> typeof(as(1L, "numeric")) >> [1] "double" >> Seems like a reasonable addition to the code, unless someone sees a problem. >> John > I guess that that some package checks (in CRAN + Bioc + ... - > land) will break, > but I still think we should add such a coercion to R. > Martin Hmm... I've tried to add the above to R and do notice that there are consequences that may be larger than anticipated: Here is example code: myN <- setClass("myN", contains="numeric") myNid <- setClass("myNid", contains="numeric", representation(id="character")) NN <- setClass("NN", representation(x="numeric")) (m1 <- myN (1:3)) (m2 <- myNid(1:3, id = "i3")) tools::assertError(NN (1:3))# in all R versions ## # current R | new R ## # -----------|---------- class(getDataPart(m1)) # integer | numeric class(getDataPart(m2)) # integer | numeric In other words, with the above setting, the traditional gentleperson's agreement in S and R, __ "numeric" sometimes conveniently means "integer" or "double" __ will be slightly less often used ... which of course may be a very good thing. However, it breaks strict back compatibility also in cases where the previous behavior may have been preferable: After all integer vectors need only have the space of doubles. Shall we still go ahead and do apply this change to R-devel and then all package others will be willing to update where necessary? As this may affect the many hundreds of bioconductor packages using S4 classes, I am -- exceptionally -- cross posting to the bioc-devel list. Martin Maechler >> On Dec 7, 2015, at 3:37 PM, Benjamin Tyner <btyner at gmail.com> wrote: >>> Perhaps it is not that surprising, given that >>> >>> > mode(1L) >>> [1] "numeric" >>> >>> and >>> >>> > is.numeric(1L) >>> [1] TRUE >>> >>> On the other hand, this is curious, to say the least: >>> >>> > is.double(as(1L, "double")) >>> [1] FALSE >>> >>>> Here's the surprising behavior: >>>> >>>> x <- 1L >>>> xx <- as(x, "numeric") >>>> class(xx) >>>> ## [1] "integer" >>>> >>>> It occurs because the call to `as(x, "numeric")` dispatches the coerce >>>> S4 method for the signature `c("integer", "numeric")`, whose body is >>>> copied in below. >>>> >>>> function (from, to = "numeric", strict = TRUE) >>>> if (strict) { >>>> class(from) <- "numeric" >>>> from >>>> } else from >>>> >>>> This in turn does nothing, even when strict=TRUE, because that >>>> assignment to class "numeric" has no effect: >>>> >>>> x <- 10L >>>> class(x) <- "numeric" >>>> class(x) >>>> [1] "integer" >>>> >>>> Is this the desired behavior for `as(x, "numeric")`? >>> >>> ______________________________________________ >>> R-devel at r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel This email message may contain legally privileged and/or confidential information. If you are not the intended recipient(s), or the employee or agent responsible for the delivery of this message to the intended recipient(s), you are hereby notified that any disclosure, copying, distribution, or use of this email message is prohibited. If you have received this message in error, please notify the sender immediately by e-mail and delete this email message from your computer. Thank you.
Martin Maechler
2015-Dec-12 09:32 UTC
[Rd] For integer vectors, `as(x, "numeric")` has no effect.
>>>>> John Chambers <jmc at r-project.org> >>>>> on Fri, 11 Dec 2015 10:11:05 -0800 writes:> Somehow, the most obvious fixes are always back-incompatible these days. > The example intrigued me, so I looked into it a bit (should have been doing something else, but ....) > You're right that this is the proverbial thin-edge-of-the-wedge. > The problem is in setDataPart(), which will be called whenever a class extends one of the vector types. > It does > as(value, dataClass) > The key point is that the third argument to as(), strict=TRUE by default. So, yes, the change will cause all integer vectors to become double when the class extends "numeric". Generally, strict=TRUE makes sense here and of course changing THAT would open up yet more incompatibilities. > For back compatibility, one would have to have some special code in setDataPart() for the case of integer/numeric. > John > (Historically, the original sin was probably not making a distinction between "numeric" as a virtual class and "double" as a type/class.) Yes, indeed. In the mean time, I've seen more cases where "the change will cause all integer vectors to become double when the class extends "numeric". seems detrimental. OTOH, I still think we could go in the right direction --- hopefully along the wishes of bioconductor S4 development, see Martin Morgan's e-mail: [This is all S4 - only; should not much affect base R / S3] Currently, "integer" is a subclass of "numeric" and so the "integer become double" part seems unwanted to me. OTOH, it would really make sense to more formally have the basic subclasses of "numeric" to be "integer" and "double", and to let as(*, "double") to become different to as(*, "numeric") [Again, this is just for the S4 classes and as() coercions, *not* e.g. for as.numeric() / as.double() !] In the DEPRECATED part of the NEWS for R 2.7.0 (April 2008) we have had o The S4 pseudo-classes "single" and double have been removed. (The S4 class for a REALSXP is "numeric": for back-compatibility as(x, "double") coerces to "numeric".) I think the removal of "single" was fine, but in hindsight, maybe the removal of "double" -- which was partly broken then -- possibly could rather have been a fixup of "double" along the following Current "thought experiment proposal" : 1) "numeric" := {"integer", "double"} { class - subclasses } 2) as(1L, "numeric") continues to return 1L .. since integer is one case of "numeric" 3) as(1L, "double") newly returns 1.0 {and in fact would be "equivalent" to as.double(1L)} After the above change, S4 as(*, "double") would correspond to S3 as.double but as(*, "numeric") would continue to differ from as.numeric(*), the former *not* changing integers to double. Martin > On Dec 11, 2015, at 1:25 AM, Martin Maechler <maechler at stat.math.ethz.ch> wrote: >>>>>>> Martin Maechler <maechler at stat.math.ethz.ch> >>>>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes: >> >>>>>>> John Chambers <jmc at r-project.org> >>>>>>> on Mon, 7 Dec 2015 16:05:59 -0800 writes: >> >>>> We do need an explicit method here, I think. >>>> The issue is that as() uses methods for the generic function coerce() but cannot use inheritance in the usual way (if it did, you would be immediately back with no change, since "integer" inherits from "numeric"). >> >>>> Copying in the general method for coercing to "numeric" as an explicit method for "integer" gives the expected result: >> >>>>> setMethod("coerce", c("integer", "numeric"), getMethod("coerce", c("ANY", "numeric"))) >>>> [1] "coerce" >>>>> typeof(as(1L, "numeric")) >>>> [1] "double" >> >>>> Seems like a reasonable addition to the code, unless someone sees a problem. >>>> John >> >>> I guess that that some package checks (in CRAN + Bioc + ... - >>> land) will break, >>> but I still think we should add such a coercion to R. >> >>> Martin >> >> Hmm... I've tried to add the above to R >> and do notice that there are consequences that may be larger than >> anticipated: >> >> Here is example code: >> >> myN <- setClass("myN", contains="numeric") >> myNid <- setClass("myNid", contains="numeric", representation(id="character")) >> NN <- setClass("NN", representation(x="numeric")) >> >> (m1 <- myN (1:3)) >> (m2 <- myNid(1:3, id = "i3")) >> tools::assertError(NN (1:3))# in all R versions >> >> ## # current R | new R >> ## # -----------|---------- >> class(getDataPart(m1)) # integer | numeric >> class(getDataPart(m2)) # integer | numeric >> >> >> In other words, with the above setting, the traditional >> gentleperson's agreement in S and R, >> >> __ "numeric" sometimes conveniently means "integer" or "double" __ >> >> will be slightly less often used ... which of course may be a >> very good thing. >> >> However, it breaks strict back compatibility also in cases where >> the previous behavior may have been preferable: >> After all integer vectors need only have the space of doubles. >> >> Shall we still go ahead and do apply this change to R-devel >> and then all package others will be willing to update where necessary? >> >> As this may affect the many hundreds of bioconductor packages >> using S4 classes, I am -- exceptionally -- cross posting to the >> bioc-devel list. >> >> Martin Maechler >> >> >>>> On Dec 7, 2015, at 3:37 PM, Benjamin Tyner <btyner at gmail.com> wrote: >> >>>>> Perhaps it is not that surprising, given that >>>>>>>>>> mode(1L)>>>>> [1] "numeric" >>>>> >>>>> and >>>>>>>>>> is.numeric(1L)>>>>> [1] TRUE >>>>> >>>>> On the other hand, this is curious, to say the least: >>>>>>>>>> is.double(as(1L, "double"))>>>>> [1] FALSE >>>>>>>>>> Here's the surprising behavior: >>>>> >>>>> x <- 1L >>>>> xx <- as(x, "numeric") >>>>> class(xx) >>>>> ## [1] "integer" >>>>> >>>>> It occurs because the call to `as(x, "numeric")` dispatches the coerce >>>>> S4 method for the signature `c("integer", "numeric")`, whose body is >>>>> copied in below. >>>>> >>>>> function (from, to = "numeric", strict = TRUE) >>>>> if (strict) { >>>>> class(from) <- "numeric" >>>>> from >>>>> } else from >>>>> >>>>> This in turn does nothing, even when strict=TRUE, because that >>>>> assignment to class "numeric" has no effect: >>>>> >>>>> x <- 10L >>>>> class(x) <- "numeric" >>>>> class(x) >>>>> [1] "integer" >>>>> >>>>> Is this the desired behavior for `as(x, "numeric")`?>>>>> >>>>> ______________________________________________ >>>>> R-devel at r-project.org mailing list >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel >> >>>> ______________________________________________ >>>> R-devel at r-project.org mailing list >>>> https://stat.ethz.ch/mailman/listinfo/r-devel >> >>> ______________________________________________ >>> R-devel at r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel
Reasonably Related Threads
- For integer vectors, `as(x, "numeric")` has no effect.
- For integer vectors, `as(x, "numeric")` has no effect.
- For integer vectors, `as(x, "numeric")` has no effect.
- For integer vectors, `as(x, "numeric")` has no effect.
- For integer vectors, `as(x, "numeric")` has no effect.