The answer becomes obvious if you read ?outer:
Details: ‘X’ and ‘Y’ must be suitable arguments for ‘FUN’. Each will be extended by ‘rep’ to length the products of the lengths of ‘X’ and ‘Y’ before ‘FUN’ is called. ‘FUN’ is called with these two extended vectors as arguments. Therefore, it must be a vectorized function (or the name of one), expecting at least two arguments.
Think about what you are doing, you are concatenating two vectors into one vector, then sum the first and second elements of this vector. fun1() on the other hand does the vectorised sum of the inputs, so the returned object is of the same length as the individual lengths of the inputs. In fun2(), the output is a vector of length 1 and it was expecting 25.
The way to make the idea behind fun2() work is to cbind() not c() the two inputs:
> fun3 <- function(x, y) { z <- cbind(x, y); z[,1] + z[,2]} > outer(seq(1,5,length=5),seq(6,10,length=5),fun3) [,1] [,2] [,3] [,4] [,5] [1,] 7 8 9 10 11 [2,] 8 9 10 11 12 [3,] 9 10 11 12 13 [4,] 10 11 12 13 14 [5,] 11 12 13 14 15