[R] dispatch on functions (was: Re: ifelse(logical, function1, function2) does not work)

Deepayan Sarkar deepayan.sarkar at gmail.com
Mon Oct 9 22:13:23 CEST 2006


On 10/7/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> I have noticed that dispatch on functions seems not to work
> in another case too.  We define + on functions (I have ignored
> the niceties of sorting out the environments as we don't really
> need it for this example) but when we try to use it, it fails even
> though in the second example if we run it explicitly it succeeds:
>
> > "+.function" <- function(x, y) function(z) x(z) + y(z)
> > sin+cos
> Error in sin + cos : non-numeric argument to binary operator
> > "+.function"(sin, cos)
> function(z) x(z) + y(z)
> <environment: 0x01c4ae7c>

I think that's because

> oldClass(sin)
NULL

?S3groupGeneric says:

     Note that a method will used for either one of these groups or one
     of its members _only_ if it corresponds to a '"class"' attribute,
     as the internal code dispatches on 'oldClass' and not on 'class'.
     This is for efficiency: having to dispatch on, say, 'Ops.integer'
     would be too slow.

To generalise your example,

Ops.function <-
    function (e1, e2 = NULL)
{
    FUN <-
        get(.Generic,
            envir = parent.frame(),
            mode = "function")
    ans <-
        function(x) {
            if (is.null(e2))
                "FUN"(e1(x))
            else
                "FUN"(e1(x),
                      if (is.function(e2)) e2(x)
                      else e2)
        }
    oldClass(ans) <- "function"
    ans
}

gives me:

> oldClass(sin) <- oldClass(cos) <- "function"
> (sin^2 + cos^2)(runif(10, 0, 2 * pi))
 [1] 1 1 1 1 1 1 1 1 1 1

I had expected the issue of environments to be non-trivial, but things
seem to magically [1] work out.

Deepayan


[1] http://www.quotationspage.com/quote/776.html



More information about the R-help mailing list