A nested nozzle would do the trick:
sapply(l, function(x) sapply(l, function(y) foo(x,y)))
I was interested in @A. Webb. Here are some benchmarking options:
R> for(i in 1:50) l[[i]] <- sample(0:9, 5, T) R> microbenchmark(sapply(l, function(x) sapply(l, function(y) foo(x,y))), outer(l,l,Vectorize(foo)), time=1000) Unit: nanoseconds expr min lq sapply(l, function(x) sapply(l, function(y) foo(x, y))) 7493739 8479127.0 outer(l, l, Vectorize(foo)) 6778098 8316362.5 time 5 48.5 mean median uq max neval 1.042e+07 1.027e+07 1.155e+07 17982289 100 1.030e+07 1.002e+07 1.187e+07 16076063 100 1.672e+02 1.385e+02 1.875e+02 914 100 R> for(i in 1:500) l[[i]] <- sample(0:9, 5, T) R> microbenchmark(sapply(l, function(x) sapply(l, function(y) foo(x,y))), outer(l,l,Vectorize(foo)), times=100) Unit: milliseconds expr min lq mean sapply(l, function(x) sapply(l, function(y) foo(x, y))) 677.3 768.5 820.4 outer(l, l, Vectorize(foo)) 828.6 903.0 958.3 median uq max neval 815.9 842.7 1278 100 930.7 960.5 1819 100
So, for small lists, the external solution runs a little faster, but for larger lists it seems that the solution to nested sapply might be a little faster.