Why does a custom function called is.numeric.factor break lattice?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Why does a custom function called is.numeric.factor break lattice?

Sebastien Bihorel
Hi,

Pretty much everything is in the title of the post. An example is below.

library(lattice)
data <-
data.frame(x=rep(1:10,8),y=rnorm(80),trt=factor(rep(1:4,each=20)),groups=rep(1:8,each=10))
xyplot <- xyplot(y~x|trt,data,groups=groups)

is.numeric.factor <- function(){
   print('hello world')
}

xyplot <- xyplot(y~x|trt,data,groups=groups)

Thanks for shedding some light on this.

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Bert Gunter-2
Think about it.

I shall assume that you are familiar with S3 methods.  What do you
think would happen when xyplot code calls is.numeric() on a factor
object expecting it to call the is.numeric primitive but, instead,
finding a factor method defined, calls that? Note that your factor
method has no arguments, but the is.numeric() primitive does. Hence
when the code calls the primitive on the factor object, the error you
saw is thrown.

I would say that this is a weakness of the informal S3 "class" system,
although you probably should not have been surprised that is.numeric
is called on factors as the "x" argument, so you were inviting trouble
by defining a factor method that overrides this behavior.
Nevertheless, I would argue that one cannot know in general when this
occurs for other S3 classes, and that therefore allowing methods for
is.numeric() is dangerous.

Of course, full qualification in the original xyplot code
(base::is.numeric() rather than is.numeric() ) would avoid such
things, but that's a drag.

Contrary opinions and corrections to any flawed understanding on my
part are welcome, of course.

Cheers,
Bert


Bert Gunter

"Data is not information. Information is not knowledge. And knowledge
is certainly not wisdom."
   -- Clifford Stoll


On Sun, Nov 15, 2015 at 6:22 PM, sbihorel
<[hidden email]> wrote:

> Hi,
>
> Pretty much everything is in the title of the post. An example is below.
>
> library(lattice)
> data <-
> data.frame(x=rep(1:10,8),y=rnorm(80),trt=factor(rep(1:4,each=20)),groups=rep(1:8,each=10))
> xyplot <- xyplot(y~x|trt,data,groups=groups)
>
> is.numeric.factor <- function(){
>   print('hello world')
> }
>
> xyplot <- xyplot(y~x|trt,data,groups=groups)
>
> Thanks for shedding some light on this.
>
> ______________________________________________
> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Jeff Newmiller
In reply to this post by Sebastien Bihorel
You need to read about S3 classes, and either make your custom function behave the way that function needs to behave or use a different function name for your custom function.

I think this is an example of the old saying that if it hurts when you slam your head against the wall, then don't do that.
---------------------------------------------------------------------------
Jeff Newmiller                        The     .....       .....  Go Live...
DCN:<[hidden email]>        Basics: ##.#.       ##.#.  Live Go...
                                      Live:   OO#.. Dead: OO#..  Playing
Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
/Software/Embedded Controllers)               .OO#.       .OO#.  rocks...1k
---------------------------------------------------------------------------
Sent from my phone. Please excuse my brevity.

On November 15, 2015 6:22:42 PM PST, sbihorel <[hidden email]> wrote:

>Hi,
>
>Pretty much everything is in the title of the post. An example is
>below.
>
>library(lattice)
>data <-
>data.frame(x=rep(1:10,8),y=rnorm(80),trt=factor(rep(1:4,each=20)),groups=rep(1:8,each=10))
>xyplot <- xyplot(y~x|trt,data,groups=groups)
>
>is.numeric.factor <- function(){
>   print('hello world')
>}
>
>xyplot <- xyplot(y~x|trt,data,groups=groups)
>
>Thanks for shedding some light on this.
>
>______________________________________________
>[hidden email] mailing list -- To UNSUBSCRIBE and more, see
>https://stat.ethz.ch/mailman/listinfo/r-help
>PLEASE do read the posting guide
>http://www.R-project.org/posting-guide.html
>and provide commented, minimal, self-contained, reproducible code.

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Sebastien Bihorel
In reply to this post by Bert Gunter-2
Hi,

Interesting, based upon my understanding of S3 methods, I would have
assumed that my function would be applied to objects of class
"numeric.factor". I was not aware of this multiple "dispatch".

Thanks for pointing this out.


On 11/15/2015 9:42 PM, Bert Gunter wrote:

> Think about it.
>
> I shall assume that you are familiar with S3 methods.  What do you
> think would happen when xyplot code calls is.numeric() on a factor
> object expecting it to call the is.numeric primitive but, instead,
> finding a factor method defined, calls that? Note that your factor
> method has no arguments, but the is.numeric() primitive does. Hence
> when the code calls the primitive on the factor object, the error you
> saw is thrown.
>
> I would say that this is a weakness of the informal S3 "class" system,
> although you probably should not have been surprised that is.numeric
> is called on factors as the "x" argument, so you were inviting trouble
> by defining a factor method that overrides this behavior.
> Nevertheless, I would argue that one cannot know in general when this
> occurs for other S3 classes, and that therefore allowing methods for
> is.numeric() is dangerous.
>
> Of course, full qualification in the original xyplot code
> (base::is.numeric() rather than is.numeric() ) would avoid such
> things, but that's a drag.
>
> Contrary opinions and corrections to any flawed understanding on my
> part are welcome, of course.
>
> Cheers,
> Bert
>
>
> Bert Gunter
>
> "Data is not information. Information is not knowledge. And knowledge
> is certainly not wisdom."
>     -- Clifford Stoll
>
>
> On Sun, Nov 15, 2015 at 6:22 PM, sbihorel
> <[hidden email]> wrote:
>> Hi,
>>
>> Pretty much everything is in the title of the post. An example is below.
>>
>> library(lattice)
>> data <-
>> data.frame(x=rep(1:10,8),y=rnorm(80),trt=factor(rep(1:4,each=20)),groups=rep(1:8,each=10))
>> xyplot <- xyplot(y~x|trt,data,groups=groups)
>>
>> is.numeric.factor <- function(){
>>    print('hello world')
>> }
>>
>> xyplot <- xyplot(y~x|trt,data,groups=groups)
>>
>> Thanks for shedding some light on this.
>>
>> ______________________________________________
>> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Bert Gunter-2
There is no multiple dispatch; just multiple misunderstanding.

The generic function is "is.numeric" . Your method for factors is
"is.numeric.factor".

You need to re-study.

Cheers,
Bert


Bert Gunter

"Data is not information. Information is not knowledge. And knowledge
is certainly not wisdom."
   -- Clifford Stoll


On Mon, Nov 16, 2015 at 5:00 AM, sbihorel
<[hidden email]> wrote:

> Hi,
>
> Interesting, based upon my understanding of S3 methods, I would have assumed
> that my function would be applied to objects of class "numeric.factor". I
> was not aware of this multiple "dispatch".
>
> Thanks for pointing this out.
>
>
> On 11/15/2015 9:42 PM, Bert Gunter wrote:
>>
>> Think about it.
>>
>> I shall assume that you are familiar with S3 methods.  What do you
>> think would happen when xyplot code calls is.numeric() on a factor
>> object expecting it to call the is.numeric primitive but, instead,
>> finding a factor method defined, calls that? Note that your factor
>> method has no arguments, but the is.numeric() primitive does. Hence
>> when the code calls the primitive on the factor object, the error you
>> saw is thrown.
>>
>> I would say that this is a weakness of the informal S3 "class" system,
>> although you probably should not have been surprised that is.numeric
>> is called on factors as the "x" argument, so you were inviting trouble
>> by defining a factor method that overrides this behavior.
>> Nevertheless, I would argue that one cannot know in general when this
>> occurs for other S3 classes, and that therefore allowing methods for
>> is.numeric() is dangerous.
>>
>> Of course, full qualification in the original xyplot code
>> (base::is.numeric() rather than is.numeric() ) would avoid such
>> things, but that's a drag.
>>
>> Contrary opinions and corrections to any flawed understanding on my
>> part are welcome, of course.
>>
>> Cheers,
>> Bert
>>
>>
>> Bert Gunter
>>
>> "Data is not information. Information is not knowledge. And knowledge
>> is certainly not wisdom."
>>     -- Clifford Stoll
>>
>>
>> On Sun, Nov 15, 2015 at 6:22 PM, sbihorel
>> <[hidden email]> wrote:
>>>
>>> Hi,
>>>
>>> Pretty much everything is in the title of the post. An example is below.
>>>
>>> library(lattice)
>>> data <-
>>>
>>> data.frame(x=rep(1:10,8),y=rnorm(80),trt=factor(rep(1:4,each=20)),groups=rep(1:8,each=10))
>>> xyplot <- xyplot(y~x|trt,data,groups=groups)
>>>
>>> is.numeric.factor <- function(){
>>>    print('hello world')
>>> }
>>>
>>> xyplot <- xyplot(y~x|trt,data,groups=groups)
>>>
>>> Thanks for shedding some light on this.
>>>
>>> ______________________________________________
>>> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide
>>> http://www.R-project.org/posting-guide.html
>>> and provide commented, minimal, self-contained, reproducible code.
>
>
>

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Duncan Murdoch-2
On 16/11/2015 10:22 AM, Bert Gunter wrote:
> There is no multiple dispatch; just multiple misunderstanding.
>
> The generic function is "is.numeric" . Your method for factors is
> "is.numeric.factor".
>
> You need to re-study.


I think the problem is with S3.  "is.numeric.factor" could be a
"numeric.factor" method for the "is" generic, or a "factor" method for
the "is.numeric" generic.  Using names with dots is a bad idea. This
would be all be simpler and less ambiguous if the class had been named
"numeric_factor" or "numericFactor" or anything without a dot.

Duncan Murdoch

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Bert Gunter-2
Thanks Duncan. You are right; I missed this.

Namespaces and full qualification seems the only reliable solution to
the general issue though -- right?

Cheers,
Bert





Bert Gunter

"Data is not information. Information is not knowledge. And knowledge
is certainly not wisdom."
   -- Clifford Stoll


On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
<[hidden email]> wrote:

> On 16/11/2015 10:22 AM, Bert Gunter wrote:
>>
>> There is no multiple dispatch; just multiple misunderstanding.
>>
>> The generic function is "is.numeric" . Your method for factors is
>> "is.numeric.factor".
>>
>> You need to re-study.
>
>
>
> I think the problem is with S3.  "is.numeric.factor" could be a
> "numeric.factor" method for the "is" generic, or a "factor" method for the
> "is.numeric" generic.  Using names with dots is a bad idea. This would be
> all be simpler and less ambiguous if the class had been named
> "numeric_factor" or "numericFactor" or anything without a dot.
>
> Duncan Murdoch

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Martin Maechler
>>>>> Bert Gunter <[hidden email]>
>>>>>     on Mon, 16 Nov 2015 08:21:09 -0800 writes:

    > Thanks Duncan. You are right; I missed this.

    > Namespaces and full qualification seems the only reliable solution to
    > the general issue though -- right?

Not in this case;  full qualification is very very rarely needed
in package code (even some "schools" do use and propagate it
much more than I would recommend), and we are talking about the
lattice code, i.e., package code, not user code, here.

I.e., using  base::is.numeric()  would not help at all: It
will still find the bogous  is.numeric.factor because that is
taken before the internal default method.

Also, I'm almost sure S4 dispatch would suffer from the same
feature of S (and hence R) here:  You are allowed to define
methods for your new classes and they are used "dynamically".
(I also don't think that the problem is related to the fact that this
 a.b.c() case is S3-ambigous:  a() method for "b.c" or a.b() method for "c".)

Unfortunately, this can be misused to define methods for
existing ("base") classes in case they are handled by the default method.
OTOH, if base/stats/... already *had* a 'factor' method for
is.numeric(), be it S3 or S4, no harm would have been done by
the bad user defined is.numeric.factor definition, thanks to the
namespace technology.

To get full protection here, we would have to
store "the dispatch table for all base classes" (a pretty vague notion)
with the package at package build time or install time ("load time" is too late:
the bad  is.numeric.factor() could already be present at package load time).

I'm not sure this would be is easily feasible.... but it may be
something to envisage for R 4.0.0 ..

Martin

    > Cheers,
    > Bert

    > Bert Gunter

    > "Data is not information. Information is not knowledge. And knowledge
    > is certainly not wisdom."
    > -- Clifford Stoll


    > On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
    > <[hidden email]> wrote:
    >> On 16/11/2015 10:22 AM, Bert Gunter wrote:
    >>>
    >>> There is no multiple dispatch; just multiple misunderstanding.
    >>>
    >>> The generic function is "is.numeric" . Your method for factors is
    >>> "is.numeric.factor".
    >>>
    >>> You need to re-study.
    >>
    >>
    >>
    >> I think the problem is with S3.  "is.numeric.factor" could be a
    >> "numeric.factor" method for the "is" generic, or a "factor" method for the
    >> "is.numeric" generic.  Using names with dots is a bad idea. This would be
    >> all be simpler and less ambiguous if the class had been named
    >> "numeric_factor" or "numericFactor" or anything without a dot.
    >>
    >> Duncan Murdoch

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Bert Gunter-2
Thanks, Martin.

You have clearly stated the issue that concerned me. I am sorry that
it cannot be (easily) resolved.


Cheers,
Bert


Bert Gunter

"Data is not information. Information is not knowledge. And knowledge
is certainly not wisdom."
   -- Clifford Stoll


On Mon, Nov 16, 2015 at 8:43 AM, Martin Maechler
<[hidden email]> wrote:

>>>>>> Bert Gunter <[hidden email]>
>>>>>>     on Mon, 16 Nov 2015 08:21:09 -0800 writes:
>
>     > Thanks Duncan. You are right; I missed this.
>
>     > Namespaces and full qualification seems the only reliable solution to
>     > the general issue though -- right?
>
> Not in this case;  full qualification is very very rarely needed
> in package code (even some "schools" do use and propagate it
> much more than I would recommend), and we are talking about the
> lattice code, i.e., package code, not user code, here.
>
> I.e., using  base::is.numeric()  would not help at all: It
> will still find the bogous  is.numeric.factor because that is
> taken before the internal default method.
>
> Also, I'm almost sure S4 dispatch would suffer from the same
> feature of S (and hence R) here:  You are allowed to define
> methods for your new classes and they are used "dynamically".
> (I also don't think that the problem is related to the fact that this
>  a.b.c() case is S3-ambigous:  a() method for "b.c" or a.b() method for "c".)
>
> Unfortunately, this can be misused to define methods for
> existing ("base") classes in case they are handled by the default method.
> OTOH, if base/stats/... already *had* a 'factor' method for
> is.numeric(), be it S3 or S4, no harm would have been done by
> the bad user defined is.numeric.factor definition, thanks to the
> namespace technology.
>
> To get full protection here, we would have to
> store "the dispatch table for all base classes" (a pretty vague notion)
> with the package at package build time or install time ("load time" is too late:
> the bad  is.numeric.factor() could already be present at package load time).
>
> I'm not sure this would be is easily feasible.... but it may be
> something to envisage for R 4.0.0 ..
>
> Martin
>
>     > Cheers,
>     > Bert
>
>     > Bert Gunter
>
>     > "Data is not information. Information is not knowledge. And knowledge
>     > is certainly not wisdom."
>     > -- Clifford Stoll
>
>
>     > On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
>     > <[hidden email]> wrote:
>     >> On 16/11/2015 10:22 AM, Bert Gunter wrote:
>     >>>
>     >>> There is no multiple dispatch; just multiple misunderstanding.
>     >>>
>     >>> The generic function is "is.numeric" . Your method for factors is
>     >>> "is.numeric.factor".
>     >>>
>     >>> You need to re-study.
>     >>
>     >>
>     >>
>     >> I think the problem is with S3.  "is.numeric.factor" could be a
>     >> "numeric.factor" method for the "is" generic, or a "factor" method for the
>     >> "is.numeric" generic.  Using names with dots is a bad idea. This would be
>     >> all be simpler and less ambiguous if the class had been named
>     >> "numeric_factor" or "numericFactor" or anything without a dot.
>     >>
>     >> Duncan Murdoch

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Sebastien Bihorel
In reply to this post by Martin Maechler
Hi,

Thanks everyone for all your insights...

I feel that the discussion is getting way deeper and more technical and
it needs to be from the point of view of what I was trying to achieve
with my little "is.numeric.factor" function (ie, checking if an object
is a factor and if all levels of this factor can be coerced to numeric
values).

I guess that, as Duncan pointed point, using dots in function names
becomes bad practice for function starring "is". I'll rename my
function, that's it.


On 11/16/2015 11:43 AM, Martin Maechler wrote:

>>>>>> Bert Gunter <[hidden email]>
>>>>>>      on Mon, 16 Nov 2015 08:21:09 -0800 writes:
>      > Thanks Duncan. You are right; I missed this.
>
>      > Namespaces and full qualification seems the only reliable solution to
>      > the general issue though -- right?
>
> Not in this case;  full qualification is very very rarely needed
> in package code (even some "schools" do use and propagate it
> much more than I would recommend), and we are talking about the
> lattice code, i.e., package code, not user code, here.
>
> I.e., using  base::is.numeric()  would not help at all: It
> will still find the bogous  is.numeric.factor because that is
> taken before the internal default method.
>
> Also, I'm almost sure S4 dispatch would suffer from the same
> feature of S (and hence R) here:  You are allowed to define
> methods for your new classes and they are used "dynamically".
> (I also don't think that the problem is related to the fact that this
>   a.b.c() case is S3-ambigous:  a() method for "b.c" or a.b() method for "c".)
>
> Unfortunately, this can be misused to define methods for
> existing ("base") classes in case they are handled by the default method.
> OTOH, if base/stats/... already *had* a 'factor' method for
> is.numeric(), be it S3 or S4, no harm would have been done by
> the bad user defined is.numeric.factor definition, thanks to the
> namespace technology.
>
> To get full protection here, we would have to
> store "the dispatch table for all base classes" (a pretty vague notion)
> with the package at package build time or install time ("load time" is too late:
> the bad  is.numeric.factor() could already be present at package load time).
>
> I'm not sure this would be is easily feasible.... but it may be
> something to envisage for R 4.0.0 ..
>
> Martin
>
>      > Cheers,
>      > Bert
>
>      > Bert Gunter
>
>      > "Data is not information. Information is not knowledge. And knowledge
>      > is certainly not wisdom."
>      > -- Clifford Stoll
>
>
>      > On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
>      > <[hidden email]> wrote:
>      >> On 16/11/2015 10:22 AM, Bert Gunter wrote:
>      >>>
>      >>> There is no multiple dispatch; just multiple misunderstanding.
>      >>>
>      >>> The generic function is "is.numeric" . Your method for factors is
>      >>> "is.numeric.factor".
>      >>>
>      >>> You need to re-study.
>      >>
>      >>
>      >>
>      >> I think the problem is with S3.  "is.numeric.factor" could be a
>      >> "numeric.factor" method for the "is" generic, or a "factor" method for the
>      >> "is.numeric" generic.  Using names with dots is a bad idea. This would be
>      >> all be simpler and less ambiguous if the class had been named
>      >> "numeric_factor" or "numericFactor" or anything without a dot.
>      >>
>      >> Duncan Murdoch

--
Sebastien Bihorel
Cognigen Corporation
(t) +1 716 633 3463 ext 323
Cognigen Corporation, a wholly owned subsidiary of Simulations Plus, Inc.
______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

David Winsemius

> On Nov 16, 2015, at 9:35 AM, sbihorel <[hidden email]> wrote:
>
> Hi,
>
> Thanks everyone for all your insights...
>
> I feel that the discussion is getting way deeper and more technical and it needs to be from the point of view of what I was trying to achieve with my little "is.numeric.factor" function (ie, checking if an object is a factor and if all levels of this factor can be coerced to numeric values).

You seem to be asking for a compound test: first with is.factor, then to see whether all the levels could be coerced to numeric properly. I would think that you would need something like:

 if( is.factor(varname) ) { !sum(is.na(as.numeric(as.character(varname)))) } else { FALSE }


David.


>
> I guess that, as Duncan pointed point, using dots in function names becomes bad practice for function starring "is". I'll rename my function, that's it.
>
>
> On 11/16/2015 11:43 AM, Martin Maechler wrote:
>>>>>>> Bert Gunter <[hidden email]>
>>>>>>>     on Mon, 16 Nov 2015 08:21:09 -0800 writes:
>>     > Thanks Duncan. You are right; I missed this.
>>
>>     > Namespaces and full qualification seems the only reliable solution to
>>     > the general issue though -- right?
>>
>> Not in this case;  full qualification is very very rarely needed
>> in package code (even some "schools" do use and propagate it
>> much more than I would recommend), and we are talking about the
>> lattice code, i.e., package code, not user code, here.
>>
>> I.e., using  base::is.numeric()  would not help at all: It
>> will still find the bogous  is.numeric.factor because that is
>> taken before the internal default method.
>>
>> Also, I'm almost sure S4 dispatch would suffer from the same
>> feature of S (and hence R) here:  You are allowed to define
>> methods for your new classes and they are used "dynamically".
>> (I also don't think that the problem is related to the fact that this
>>  a.b.c() case is S3-ambigous:  a() method for "b.c" or a.b() method for "c".)
>>
>> Unfortunately, this can be misused to define methods for
>> existing ("base") classes in case they are handled by the default method.
>> OTOH, if base/stats/... already *had* a 'factor' method for
>> is.numeric(), be it S3 or S4, no harm would have been done by
>> the bad user defined is.numeric.factor definition, thanks to the
>> namespace technology.
>>
>> To get full protection here, we would have to
>> store "the dispatch table for all base classes" (a pretty vague notion)
>> with the package at package build time or install time ("load time" is too late:
>> the bad  is.numeric.factor() could already be present at package load time).
>>
>> I'm not sure this would be is easily feasible.... but it may be
>> something to envisage for R 4.0.0 ..
>>
>> Martin
>>
>>     > Cheers,
>>     > Bert
>>
>>     > Bert Gunter
>>
>>     > "Data is not information. Information is not knowledge. And knowledge
>>     > is certainly not wisdom."
>>     > -- Clifford Stoll
>>
>>
>>     > On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
>>     > <[hidden email]> wrote:
>>     >> On 16/11/2015 10:22 AM, Bert Gunter wrote:
>>     >>>
>>     >>> There is no multiple dispatch; just multiple misunderstanding.
>>     >>>
>>     >>> The generic function is "is.numeric" . Your method for factors is
>>     >>> "is.numeric.factor".
>>     >>>
>>     >>> You need to re-study.
>>     >>
>>     >>
>>     >>
>>     >> I think the problem is with S3.  "is.numeric.factor" could be a
>>     >> "numeric.factor" method for the "is" generic, or a "factor" method for the
>>     >> "is.numeric" generic.  Using names with dots is a bad idea. This would be
>>     >> all be simpler and less ambiguous if the class had been named
>>     >> "numeric_factor" or "numericFactor" or anything without a dot.
>>     >>
>>     >> Duncan Murdoch
>
> --
> Sebastien Bihorel
> Cognigen Corporation
> (t) +1 716 633 3463 ext 323
> Cognigen Corporation, a wholly owned subsidiary of Simulations Plus, Inc.
> ______________________________________________
> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

David Winsemius
Alameda, CA, USA

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Why does a custom function called is.numeric.factor break lattice?

Sebastien Bihorel
Thanks David,

I never seem to get my intention clear when I post to the R-help list...
I am not sure why...

Anyways, my issue was not with the test (I came up with something
similar). It was actually with the name of the function which I had to
create, given that this test needed to be used dozens of times in the
framework I work with.
My choice of function name was less than optimal and got me into all the
troubles discussed in previous posts. My own debugging identified that
the test was not the problem but the function name somehow interfered
with lattice. So I already knew how to fix my problem before posting...
just choose a different name.
My post was actually intended to clarify the reason why the function
name itself was causing the issue... which I believe it now perfectly
clear, thanks to all the previous posts.



On 11/16/2015 12:59 PM, David Winsemius wrote:

>> On Nov 16, 2015, at 9:35 AM, sbihorel <[hidden email]> wrote:
>>
>> Hi,
>>
>> Thanks everyone for all your insights...
>>
>> I feel that the discussion is getting way deeper and more technical and it needs to be from the point of view of what I was trying to achieve with my little "is.numeric.factor" function (ie, checking if an object is a factor and if all levels of this factor can be coerced to numeric values).
> You seem to be asking for a compound test: first with is.factor, then to see whether all the levels could be coerced to numeric properly. I would think that you would need something like:
>
>   if( is.factor(varname) ) { !sum(is.na(as.numeric(as.character(varname)))) } else { FALSE }
>
> —
> David.
>
>
>> I guess that, as Duncan pointed point, using dots in function names becomes bad practice for function starring "is". I'll rename my function, that's it.
>>
>>
>> On 11/16/2015 11:43 AM, Martin Maechler wrote:
>>>>>>>> Bert Gunter <[hidden email]>
>>>>>>>>      on Mon, 16 Nov 2015 08:21:09 -0800 writes:
>>>      > Thanks Duncan. You are right; I missed this.
>>>
>>>      > Namespaces and full qualification seems the only reliable solution to
>>>      > the general issue though -- right?
>>>
>>> Not in this case;  full qualification is very very rarely needed
>>> in package code (even some "schools" do use and propagate it
>>> much more than I would recommend), and we are talking about the
>>> lattice code, i.e., package code, not user code, here.
>>>
>>> I.e., using  base::is.numeric()  would not help at all: It
>>> will still find the bogous  is.numeric.factor because that is
>>> taken before the internal default method.
>>>
>>> Also, I'm almost sure S4 dispatch would suffer from the same
>>> feature of S (and hence R) here:  You are allowed to define
>>> methods for your new classes and they are used "dynamically".
>>> (I also don't think that the problem is related to the fact that this
>>>   a.b.c() case is S3-ambigous:  a() method for "b.c" or a.b() method for "c".)
>>>
>>> Unfortunately, this can be misused to define methods for
>>> existing ("base") classes in case they are handled by the default method.
>>> OTOH, if base/stats/... already *had* a 'factor' method for
>>> is.numeric(), be it S3 or S4, no harm would have been done by
>>> the bad user defined is.numeric.factor definition, thanks to the
>>> namespace technology.
>>>
>>> To get full protection here, we would have to
>>> store "the dispatch table for all base classes" (a pretty vague notion)
>>> with the package at package build time or install time ("load time" is too late:
>>> the bad  is.numeric.factor() could already be present at package load time).
>>>
>>> I'm not sure this would be is easily feasible.... but it may be
>>> something to envisage for R 4.0.0 ..
>>>
>>> Martin
>>>
>>>      > Cheers,
>>>      > Bert
>>>
>>>      > Bert Gunter
>>>
>>>      > "Data is not information. Information is not knowledge. And knowledge
>>>      > is certainly not wisdom."
>>>      > -- Clifford Stoll
>>>
>>>
>>>      > On Mon, Nov 16, 2015 at 7:42 AM, Duncan Murdoch
>>>      > <[hidden email]> wrote:
>>>      >> On 16/11/2015 10:22 AM, Bert Gunter wrote:
>>>      >>>
>>>      >>> There is no multiple dispatch; just multiple misunderstanding.
>>>      >>>
>>>      >>> The generic function is "is.numeric" . Your method for factors is
>>>      >>> "is.numeric.factor".
>>>      >>>
>>>      >>> You need to re-study.
>>>      >>
>>>      >>
>>>      >>
>>>      >> I think the problem is with S3.  "is.numeric.factor" could be a
>>>      >> "numeric.factor" method for the "is" generic, or a "factor" method for the
>>>      >> "is.numeric" generic.  Using names with dots is a bad idea. This would be
>>>      >> all be simpler and less ambiguous if the class had been named
>>>      >> "numeric_factor" or "numericFactor" or anything without a dot.
>>>      >>
>>>      >> Duncan Murdoch
>> --
>> Sebastien Bihorel
>> Cognigen Corporation
>> (t) +1 716 633 3463 ext 323
>> Cognigen Corporation, a wholly owned subsidiary of Simulations Plus, Inc.
>> ______________________________________________
>> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
> David Winsemius
> Alameda, CA, USA
>

--
Sebastien Bihorel
Cognigen Corporation
(t) +1 716 633 3463 ext 323
Cognigen Corporation, a wholly owned subsidiary of Simulations Plus, Inc.
______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.