functional programming - Why doesn't outer work the way I think it should (in R)? -
prompted @hadley's article on functionals referenced in answer today, decided revisit persistent puzzle how outer
function works (or doesn't). why fail:
outer(0:5, 0:6, sum) # while outer(0:5, 0:6, "+") succeeds
this shows how think outer
should handle function sum
:
outer <- function(x,y,fun) { mat <- matrix(na, length(x), length(y)) (i in seq_along(x)) { (j in seq_along(y)) {mat[i,j] <- fun(x[i],y[j])} } mat} > outer(0:5, 0:6, `+`) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [1,] 0 1 2 3 4 5 6 [2,] 1 2 3 4 5 6 7 [3,] 2 3 4 5 6 7 8 [4,] 3 4 5 6 7 8 9 [5,] 4 5 6 7 8 9 10 [6,] 5 6 7 8 9 10 11
ok, don't have indices aligned example, wouldn't hard fix. question why function sum
should able accept 2 arguments , return (atomic) value suitable matrix element, cannot when passed base::outer
function?
so @agstudy has given inspiration more compact version of outer
, more compact:
outer <- function(x,y,fun) { mat <- matrix(mapply(fun, rep(x, length(y)), rep(y, each=length(x))), length(x), length(y))
however, question remains. term "vectorized" ambiguous here , think "dyadic" more correct, since sin
, cos
"vectorized" in usual sense of term. there fundamental logical barrier expecting outer
expand arguments in manner non-dyadic functions can used.
and here's outer
-error connected lack of understanding of issue:
> vectorize(sum) function (..., na.rm = false) .primitive("sum") > outer(0:5, 0:6, function(x,y) vectorize(sum)(x,y) ) error in outer(0:5, 0:6, function(x, y) vectorize(sum)(x, y)) : dims [product 42] not match length of object [1]
outer(0:5, 0:6, sum)
don't work because sum
not "vectorized" (in sense of returning vector of same length 2 arguments). example should explain difference:
sum(1:2,2:3) 8 1:2 + 2:3 [1] 3 5
you can vectorize sum
using mapply
example:
identical(outer(0:5, 0:6, function(x,y)mapply(sum,x,y)), outer(0:5, 0:6,'+')) true
ps: before using outer
use browser
create function in debug mode:
outer(0:2, 1:3, function(x,y)browser()) called from: fun(x, y, ...) browse[1]> x [1] 0 1 2 0 1 2 0 1 2 browse[1]> y [1] 1 1 1 2 2 2 3 3 3 browse[1]> sum(x,y) [1] 27 ## give error browse[1]> x+y [1] 1 2 3 2 3 4 3 4 5 ## vectorized
Comments
Post a Comment