[Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-04 Thread Josh O'Brien
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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-07 Thread Benjamin Tyner

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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-07 Thread John Chambers
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


On Dec 7, 2015, at 3:37 PM, Benjamin Tyner  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@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


Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-08 Thread Martin Maechler
> John Chambers 
> 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



> On Dec 7, 2015, at 3:37 PM, Benjamin Tyner  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@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

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-11 Thread Martin Maechler
> Martin Maechler 
> on Tue, 8 Dec 2015 15:25:21 +0100 writes:

> John Chambers 
> 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  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@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

> __
> 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


Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-11 Thread John Chambers
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  wrote:

>> Martin Maechler 
>>on Tue, 8 Dec 2015 15:25:21 +0100 writes:
> 
>> John Chambers 
>>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  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@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
> 
>> __
>> R-devel@r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel


[[alternative HTML version deleted]]

__

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-11 Thread Morgan, Martin
>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-boun...@r-project.org] on behalf of Martin Maechler 
[maech...@stat.math.ethz.ch]
Sent: Friday, December 11, 2015 4:25 AM
To: John Chambers; r-devel@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 
>>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes:

>>>>> John Chambers 
>>>>> 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  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 thi

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-12 Thread Martin Maechler
> John Chambers 
> 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  
wrote:

>>> Martin Maechler 
>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes:
>> 
>>> John Chambers 
>>> 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"  __
>> 

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-19 Thread Martin Maechler
> Martin Maechler 
> on Sat, 12 Dec 2015 10:32:51 +0100 writes:

> John Chambers 
> 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

Also note that e.g.

class(pi)would return "double" instead of "numeric"

and this will break all the bad programming style usages of

  if(class(x) == "numeric")

which I tend to see in gazillions of user and even package codes
This bad (aka error prone !)  because "correct" usage would be

  if(inherits(x, "numeric"))

and that of course would *not* break after the change above.

- - - - 

A week later, I'm still pretty convinced it would be worth going
in the direction proposed above. 

But I was actually hoping for some encouragement or "mental support"...
or then to hear why you think the proposition is not good or not
viable ...


>> On Dec 11, 2015, at 1:25 AM, Martin Maechler 
 wrote:

 Martin Maechler 
 on Tue, 8 Dec 2015 15:25:21 +0100 writes:
>>> 
 John Chambers 
 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 consequenc

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2015-12-19 Thread John Chambers
As I tried to say on Dec. 11, there are two levels of "fix":

1.  The fix to the complaint in the OP's subject heading is to conform to the 
default third argument, strict=TRUE: as(1L, "numeric") == 1.0

This generates some incompatibilities, as for classes that extend "numeric". 
But still leaves class(1.0) "numeric" and typeof(1.0) "double".

The workaround for class definitions that really need NOT to coerce integers to 
double is to define a class union, say
  setClassUnion("Number", c("numeric", "integer"))
and use that for the slot.

2.  The "right" concept is arguably that "numeric" is a virtual class with two 
subclasses, "double" and "integer".  Given a time machine back to < 1998, that 
would be my choice.  But already in the 1998 S4 book, "numeric" was equated 
with "double".

so, there it is, IMO.  This is what you get with a successful open-source 
language:  Much hassle to do the "right thing" after the fact and the more 
change, the more hassle.

Fix 1. seems to me an actual bug fix, so my inclination would be to go with 
that (on r-devel), advertising that it may change the effective definition of 
some classes.

But I can sympathize with choosing 1, 2 or neither.

John

PS:  Until Jan. 4, I may be even poorer at replying than usual, while getting 
the current book off to the publisher.

On Dec 19, 2015, at 3:32 AM, Martin Maechler  wrote:

>> Martin Maechler 
>>on Sat, 12 Dec 2015 10:32:51 +0100 writes:
> 
>> John Chambers 
>>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
> 
>> oThe 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
> 
> Also note that e.g.
> 
>class(pi)would return "double" instead of "numeric"
> 
> and this will break all the bad programming style usages of
> 
>  if(class(x) == "numeric")
> 
> which I tend to see in gazillions of user and even package codes
> This bad (aka error prone !)  because "correct" usage would be
> 
>  if(inherits(x, "numeric"))
> 
> and that of course would *not* break after the change above.
> 
> - - - - 
> 
> A week later, I'm still pretty convinced it would be worth going
> in the direction proposed above. 
> 
> But I was actually hoping for some encouragement or "mental

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2016-01-04 Thread Josh O'Brien
On Dec 19, 2015, at 3:32 AM, Martin Maechler  wrote:

>> Martin Maechler 
>>on Sat, 12 Dec 2015 10:32:51 +0100 writes:
>
>> John Chambers 
>>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
>
>> oThe 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
>
> Also note that e.g.
>
>class(pi)would return "double" instead of "numeric"
>
> and this will break all the bad programming style usages of
>
>  if(class(x) == "numeric")
>
> which I tend to see in gazillions of user and even package codes
> This bad (aka error prone !)  because "correct" usage would be
>
>  if(inherits(x, "numeric"))
>
> and that of course would *not* break after the change above.
>
> - - - -
>
> A week later, I'm still pretty convinced it would be worth going
> in the direction proposed above.
>
> But I was actually hoping for some encouragement or "mental support"...
> or then to hear why you think the proposition is not good or not
> viable ...
>
>

I really like Martin Maechler's "thought experiment proposal", but (based
partly on the reception its gotten) figure I mustn't be appreciating
the complications
it would introduce..

That said, if it's decided to just make a smaller fix of as(x, "numeric"),
might it be better to make the change at the C level, to R_set_class
in $RHOME/src/main/coerce.c?

Here's the 'offending' bit of R_set_class (the C-code implementing the
R function `class<-`), which treats an INTSXP in the same way as a
REALSXP, breaking before it get coerced to REALSXP:

  else if(!strcmp("numeric", valueString)) {
  setAttrib(obj, R_ClassSymbol, R_NilValue);
  if(IS_S4_OBJECT(obj)) /* NULL class is only valid for S3 objects */
do_unsetS4(obj, value);
  switch(TYPEOF(obj)) {
  case INTSXP: case REALSXP: break;
  default: PROTECT(obj = coerceVector(obj, REALSXP));
  nProtect++;
  }
  }

Simply deleting "case INTSXP: " will let integer vectors pass
through and get converted to REALSXP by coerceVector().

This approach has a couple of advantages that (unless I'm missing
something) make it seem relatively clean:

  - It requires no additional explicit S4 "coerce" method for
signature c("integer", "numeric").

  - It simultaneously fi

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2016-01-05 Thread Martin Maechler
> Josh O'Brien 
> on Mon, 4 Jan 2016 16:16:51 -0800 writes:

> On Dec 19, 2015, at 3:32 AM, Martin Maechler  wrote:

>>> Martin Maechler  on
>>> Sat, 12 Dec 2015 10:32:51 +0100 writes:
>> 
>>> John Chambers  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
>> 
>> Also note that e.g.
>> 
>> class(pi) would return "double" instead of "numeric"
>> 
>> and this will break all the bad programming style usages
>> of
>> 
>> if(class(x) == "numeric")
>> 
>> which I tend to see in gazillions of user and even
>> package codes This bad (aka error prone !)  because
>> "correct" usage would be
>> 
>> if(inherits(x, "numeric"))
>> 
>> and that of course would *not* break after the change
>> above.
>> 
>> - - - -
>> 
>> A week later, I'm still pretty convinced it would be
>> worth going in the direction proposed above.
>> 
>> But I was actually hoping for some encouragement or
>> "mental support"...  or then to hear why you think the
>> proposition is not good or not viable ...
>> 
>> 

> I really like Martin Maechler's "thought experiment
> proposal", but (based partly on the reception its gotten)
> figure I mustn't be appreciating the complications it
> would introduce..

Actually, I've spent half day implementing it and was very
pleased about it... as matter of fact it passed *all* our checks
also in all recommended packages (*)

To do it cleanly... with very few code changes,
the *only* consequence would be that

   class(1.)

(and similar) then returned  "double" instead of "numeric".
which  *would*  be logical consequent, because indeed,

   numeric = {integer, double

Re: [Rd] For integer vectors, `as(x, "numeric")` has no effect.

2016-01-05 Thread Josh O'Brien
On Tue, Jan 5, 2016 at 1:31 AM, Martin Maechler
 wrote:
>> Josh O'Brien 
>> on Mon, 4 Jan 2016 16:16:51 -0800 writes:
>
> > On Dec 19, 2015, at 3:32 AM, Martin Maechler  stat.math.ethz.ch> wrote:
>
> >>> Martin Maechler  on
> >>> Sat, 12 Dec 2015 10:32:51 +0100 writes:
> >>
> >>> John Chambers  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
> >>
> >> Also note that e.g.
> >>
> >> class(pi) would return "double" instead of "numeric"
> >>
> >> and this will break all the bad programming style usages
> >> of
> >>
> >> if(class(x) == "numeric")
> >>
> >> which I tend to see in gazillions of user and even
> >> package codes This bad (aka error prone !)  because
> >> "correct" usage would be
> >>
> >> if(inherits(x, "numeric"))
> >>
> >> and that of course would *not* break after the change
> >> above.
> >>
> >> - - - -
> >>
> >> A week later, I'm still pretty convinced it would be
> >> worth going in the direction proposed above.
> >>
> >> But I was actually hoping for some encouragement or
> >> "mental support"...  or then to hear why you think the
> >> proposition is not good or not viable ...
> >>
> >>
>
> > I really like Martin Maechler's "thought experiment
> > proposal", but (based partly on the reception its gotten)
> > figure I mustn't be appreciating the complications it
> > would introduce..
>
> Actually, I've spent half day implementing it and was very
> pleased about it... as matter of fact it passed *all* our che