Re: coerce() methods.

Important to realize that as() does not call selectMethod() in the standard 
way, but restricts inheritance to the first argument:
               asMethod <- selectMethod("coerce", sig, optional = TRUE, 
                  c(from = TRUE, to = FALSE), fdef = coerceFun, 
A valid comparison would have to take account of this.

Once the method has been _correctly_ selected, it is stored in the internal 
table and therefore  will be returned by .findMethodInTable without repeating a 
search.

John

On Dec 25, 2015, at 11:51 PM, Herv� Pag�s <hpa...@fredhutch.org> wrote:

> Or maybe the "right" concept is that "numeric" is a virtual class
> with 3 subclasses: "complex", "double", and "integer". Anyway it's
> probably too late for implementing the "right" concept so it doesn't
> really matter.
> 
> Thanks Martin for offering to fix the as(1L, "numeric") bug. Very
> much appreciated. I guess that means fixing the class(x) <- "numeric"
> bug on integer vectors:
> 
>  > x <- 1L
>  > class(x) <- "numeric"
>  > class(x)
>  [1] "integer"
> 
> My wish for 2016: that selectMethod() always tells the truth. For
> example selectMethod("coerce", c("integer", "numeric")) doesn't
> in a fresh session, only after you call as(1L, "numeric")). Full
> story here:
> 
>  https://stat.ethz.ch/pipermail/r-devel/2010-April/057098.html
> 
> Thanks,
> H.
> 
> 
> On 12/19/2015 10:09 AM, John Chambers wrote:
>> 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 <maech...@stat.math.ethz.ch> 
>> wrote:
>> 
>>>>>>>> Martin Maechler <maech...@stat.math.ethz.ch>
>>>>>>>>    on Sat, 12 Dec 2015 10:32:51 +0100 writes:
>>> 
>>>>>>>> John Chambers <j...@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
>>> 
>>> 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 <maech...@stat.math.ethz.ch> 
>>>>> wrote:
>>> 
>>>>>>>>>>> Martin Maechler <maech...@stat.math.ethz.ch>
>>>>>>>>>>> on Tue, 8 Dec 2015 15:25:21 +0100 writes:
>>>>>> 
>>>>>>>>>>> John Chambers <j...@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 <bty...@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@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]]
>> 
>> _______________________________________________
>> bioc-de...@r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/bioc-devel
>> 
> 
> -- 
> Herv� Pag�s
> 
> Program in Computational Biology
> Division of Public Health Sciences
> Fred Hutchinson Cancer Research Center
> 1100 Fairview Ave. N, M1-B514
> P.O. Box 19024
> Seattle, WA 98109-1024
> 
> E-mail: hpa...@fredhutch.org
> Phone:  (206) 667-5791
> Fax:    (206) 667-1319
> 
> ______________________________________________
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel


        [[alternative HTML version deleted]]

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

Reply via email to