[R] variable capture in apply

Kjetil Halvorsen khal at alumni.uv.es
Tue Oct 27 20:44:50 CET 1998


The following example is from `S Poetry', page 78-79.  It
seems to indicate some error in lapply, sapply, 
or both? [It does, and below the solution is given also.]



> jjalist <- list(matrix(c(1:4),2,2),
+                 matrix(c(1,3,5,7),2,2),
+                 matrix(c(2,5,8,4),2,2))
> jjblist <- jjalist  # data for example

> debug(sapply)
> debug(lapply)
> sapply( seq(along=jjalist), function(i,x,y) 
+    {x[[i]] %*% y[[i]]}, x=jjalist, y=jjblist)
debugging in: sapply(seq(along = jjalist), function(i, x, y) {
            x[[i]] %*% y[[i]]
}, x = jjalist, y = jjblist)
debug: if (is.character(FUN)) FUN <- get(FUN, mode = "function") else if
(mode(FUN) != 
            "function") {
            farg <- substitute(FUN)
            if (mode(farg) == "name") 
                    FUN <- get(farg, mode = "function")
            else stop(paste("\"", farg, "\" is not a function", sep =
""))
}
Browse[1]> n
debug: answer <- lapply(as.list(X), FUN, ...)
Browse[1]> n
debugging in: lapply(as.list(X), FUN, ...)
debug: if (is.character(FUN)) FUN <- get(FUN, mode = "function")
Browse[1]> FUN
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

            # FUN has captured the value of X???

Browse[1]> mode(FUN)
[1] "list"
Browse[1]> x
[[1]]
     [,1] [,2]
[1,]    1    3
[2,]    2    4

[[2]]
     [,1] [,2]
[1,]    1    5
[2,]    3    7

[[3]]
     [,1] [,2]
[1,]    2    8
[2,]    5    4

Browse[1]> X
Error: Object "X" not found
Browse[1]> 

.
.
.

Playing around a little, seems to be variable capture, because

> sapply( seq(along=jjalist), function(i,xx,yy) 
+    {xx[[i]] %*% yy[[i]]}, xx=jjalist, yy=jjblist)

works as expected!  And indeed, from the source:

> sapply
function (X, FUN, ..., simplify = TRUE)  ...

but

> lapply
function (x, FUN, ...) 

so the argument to my FUN was captured here?

And indeed, after redefing:

lapply <- 
function (X, FUN, ...) 
{
            if (is.character(FUN)) 
                    FUN <- get(FUN, mode = "function")
            if (mode(FUN) != "function") 
                    stop(paste("\"", FUN, "\" is not a function", 
                         sep = " "))
            if (!is.list(X)) 
                    X <- as.list(X)
            rval <- vector("list", length(X))
            for (i in seq(along = X)) rval[i] <- list(FUN(X[[i]], ...))
            # keep `names' !
            names(rval) <- names(X)
            return(rval)
}
 everything works out nice.  

 [The same change should be made in tapply, while apply is good.]

Kjetil Halvorsen.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list