11

Those two functions should give similar results, don't they?

f1 <- function(x, y) {
   if (missing(y)) {
      out <- x
   } else {
      out <- c(x, y)
   }
   return(out)
}

f2 <- function(x, y) ifelse(missing(y), x, c(x, y))

Results:

> f1(1, 2)
[1] 1 2
> f2(1, 2)
[1] 1
Tim
  • 7,075
  • 6
  • 29
  • 58
  • 4
    Do the answers [here](http://stackoverflow.com/q/9449184/1270695) help? – A5C1D2H2I1M1N2O1R2T1 Jan 05 '15 at 11:40
  • 2
    I can't give you an explanation as to why, but if you include `return` statements in `f2` you get the same result: `f2 <- function(x, y) ifelse(missing(y), return(x), return(c(x, y)))`. – tospig Jan 05 '15 at 11:41
  • @DavidArenburg I hesitate to close as duplicate (though I might vote for it if I could) because it is not obvious at all from the *questions* that they are duplicates, but only from the answers (which doesn't make this easy to search). I think the issue is slightly more obvious in this question than in the other. – Roland Jan 05 '15 at 12:37
  • @Roland, then maybe edit the Qs title accordingly? I don't think `missing` as anything to do here – David Arenburg Jan 09 '15 at 10:25
  • @DavidArenburg and Roland - I changed the title to be more descriptive. – Tim Jan 09 '15 at 10:45

2 Answers2

12

This is not related to missing, but rather to your wrong use of ifelse. From help("ifelse"):

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.

The "shape" of your test is a length-one vector. Thus, a length-one vector is returned. ifelse is not just different syntax for if and else.

Roland
  • 127,288
  • 10
  • 191
  • 288
5

The same result occurs outside of the function:

> ifelse(FALSE, 1, c(1, 2))
[1] 1

The function ifelse is designed for use with vectorised arguments. It tests the first element of arg1, and if true returns the first element of arg2, if false the first element of arg3. In this case it ignores the trailing elements of arg3 and returns only the first element, which is equivalent to the TRUE value in this case, which is the confusing part. It is clearer what is going on with different arguments:

> ifelse(FALSE, 1, c(2, 3))
[1] 2

> ifelse(c(FALSE, FALSE), 1, c(2,3))
[1] 2 3

It is important to remember that everything (even length 1) is a vector in R, and that some functions deal with each element individually ('vectorised' functions) and some with the vector as a whole.

Tarquinnn
  • 501
  • 3
  • 8