[R] ifelse(logical, function1, function2) does not work

Gabor Grothendieck ggrothendieck at gmail.com
Sat Oct 7 18:28:40 CEST 2006


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>

By the way, rep(list(sin), 5) and rep(list(matrix(1:4, 2)), 5) will
create lists of functions and matrices although I agree that the
way it works is pretty strange.

On 10/7/06, Rolf Turner <rolf at erdos.math.unb.ca> wrote:
> Peter Dalgaard writes:
>
> > Alberto Vieira Ferreira Monteiro <albmont at centroin.com.br> writes:
> >
> > > Why this kind of assignment does not work?
> > >
> > >   n <- 1
> > >   f <- ifelse(n == 1, sin, cos)
> > >   f(pi)
> >
> > It's not supposed to.
> >
> >      'ifelse' returns a value with the same shape as 'test' which is
> >      filled with elements selected from either 'yes' or 'no' depending
> >      on whether the element of 'test' is 'TRUE' or 'FALSE'.
> >
> > which makes very little sense if yes and no are functions.
>
>        I think that's a debatable assertion.  Why might I
>        not want a vector, or rather a list, of functions?
>
>        (Mr. Monteiro's real sin is a very common one ---
>        using ifelse() unnecessarily/inappropriately, i.e.
>        when the ``test'' argument is a scalar.)
>
>        But to get back to trying to apply ifelse() with functions
>        for the ``yes'' and ``no'' arguments:
>
>        What's happening is really a feature of the ***rep()***
>        function, and the way that it treats objects of different
>        natures.  If you do rep(1,5) you get a vector of 5 1's.  If
>        you do rep(sin,5) you get an error message.
>
>        Note however that if you do
>
>                > x <- list(a=17,b=42)
>                > junk <- rep(x,5)
>
>        then junk is a list of length 5, each entry of which is
>        a copy of x.  I.e. rep() works as expected (?) with lists.
>
>        And if you make the assignments
>
>                > y <- list(a=42,b=17)
>                > n <- 1
>
>        and then execute
>
>                > ifelse(n==1,x,y)
>
>        you get a copy of x.  So rep does its thing with numbers (and
>        vectors) and lists, but not with *functions*.
>
>        What else might one try to rep?  What about matrices?  Works,
>        but the matrix is coerced to a vector first.  One might have
>        naively hoped that rep(M,5) would yield a list of length 5,
>        each entry of which was a copy of M.  But it doesn't; it
>        gives a vector of length 5*nrow(M)*ncol(M) consisting of
>        the data of M strung out in column order, 5 times over.
>
>        The function rep() seems to have (S3) methods associated
>        with it --- rep.Date, rep.factor, etc., but no generic
>        function.  I.e. rep() does not seem to dispatch methods.
>        Nor is there a rep.default().
>
>        I wrote a ``method'' for the matrix class
>
>                rep.matrix <- function(x,times) {
>                        if(!inherits(x,"matrix"))
>                                stop("Argument x is not a matrix.\n")
>                        ans <- list()
>                        ans[1:times] <- list(x)
>                        ans
>                }
>
>        That seemed to give the result I expected/wanted; rep(M,5)
>        did indeed give a list of length 5, each entry of which was a
>        copy of M.
>
>        However a similar ``method'' for functions did not work;
>        rep(sin,5) gave the same old ``object is not subsettable''
>        error.
>
>        But if I called rep.function() *explicitly* I got what I
>        wanted.  I.e.
>
>                > rep.function(sin,5)
>
>        gave a list of length 5 each entry of which was
>        ``.Primitive("sin")''.
>
>        Questions:  How do methods for rep() get dispatched
>        when there is no generic rep()?
>
>                    How come the matrix method that I wrote
>        got dispatched, but the function method didn't?
>
>                                cheers,
>
>                                        Rolf Turner
>                                        rolf at math.unb.ca
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> 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.
>



More information about the R-help mailing list