[R] What if there's nothing to dispatch on?
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Thu Sep 2 01:29:32 CEST 2021
On 01/09/2021 6:29 p.m., Rolf Turner wrote:
>
> On Wed, 1 Sep 2021 05:35:03 -0400
> Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
>
>> On 31/08/2021 11:59 p.m., Rolf Turner wrote:
>>>
>>> I'm trying to build a pair of (S3) methods, a "formula" method and a
>>> "default" method. The methods have a "data" argument. If the
>>> variables in question cannot be found in "data" then they should be
>>> sought in the global environment.
>>>
>>> My problem is that the generic dispatches on its first argument,
>>> which may be a formula (in which case it of course dispatches to
>>> the formula method) or the first of the variables. If this
>>> variable exists in the global environment then all is well. But if
>>> it doesn't exist there, then the generic falls over with an error
>>> of the form "object 'x' not found" --- because there isn't anything
>>> to dispatch on.
>>>
>>> I'd *like* to be able to tell the generic that if "x" is not found
>>> then it should dispatch to the default method (which will, if the
>>> call is sensible, find "x" in "data").
>>>
>>> Is there any way to tell the generic to do this?
>>>
>>> Or is there any other way out of this dilemma? (Other than "Give up
>>> and go to the pub", which I cannot currently do since Auckland is
>>> in Level 4 lockdown. :-) )
>>>
>>
>> That design is probably not a good idea: what if one of the
>> variables in data matches the name of some other object in the global
>> environment? Then it would dispatch on that other object, and things
>> won't go well.
>>
>> But here's a way to shoot yourself in the foot:
>>
>> function(x) {
>> x1 <- try(x, silent = TRUE)
>> if (inherits(x1, "try-error"))
>> foo.default(x)
>> else
>> UseMethod("foo", x)
>> }
>>
>> Happy shooting!
>
> Thanks Duncan. I don't understand your warning, but.
>
> If I call foo(y ~ x,data=xxx) I want the generic to dispatch to the
> formula method. That method will then look for y and x first in xxx,
> and if it can't find them there it then will look for them in the global
> environment.
>
> If I call foo(x,y,data=xxx) I want the generic to dispatch to the
> default method, irrespective of whether x exists in the global
> environment. I can't figure out how to arrange this. As before
> (if I could arrange for the dispatch to happen as desired) I would want
> the method to look for y and x first in xxx, and if it can't find them
> there it then will look for them in the global environment.
>
> It doesn't matter there is an "x" in both xxx and in the global
> environment; the methods will/should use the "x" from xxx.
>
> I don't see a problem with respect to this issue.
>
> Whatever. I can't get your shoot-in-the-foot solution to work anyway.
>
> If I set
>
> xxx <- data.frame(u=1:10,v=rnorm(10))
>
> and do
>
> foo(x=u,y=v,data=xxx)
>
> I get
>
>> Error in foo.default(x, y, data) : Cannot find x.
>
> The argument names need to match up. Note that calling foo.default()
> directly works:
>
> foo.default(x=u,y=v,data=xxx)
>
> runs just fine.
>
> I think I'm going to have to give up on the classes-and-methods
> approach. I *think* I can see a way through with a using a single
> function and if-statements based on your "try" idea.
>
I don't know the header of your foo() method, but let's suppose foo() is
foo <- function(x, data, ...) {
UseMethod("foo")
}
with
foo.formula <- function(x, data, ...) {
# do something with the formula x
}
foo.default <- function(x, data, ...) {
# do the default thing.
}
Now you have
xxx <- data.frame(u = 1:10, v = rnorm(10))
foo(x = u, y = v, data = xxx)
You want this to dispatch to the default method, because u is not a
formula, it's a column in xxx. But how do you know that? Maybe in some
other part of your code you have
u <- someresponse ~ somepredictor
So now u *is* a formula, and this will dispatch to the formula method,
causing havoc.
I think Bill's suggestion doesn't help here. To do what you want to do
doesn't really match what S3 is designed to do.
Duncan
More information about the R-help
mailing list