[R] ifelse(logical, function1, function2) does not work
Rolf Turner
rolf at erdos.math.unb.ca
Sat Oct 7 18:04:06 CEST 2006
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
More information about the R-help
mailing list