From michael.weylandt at gmail.com  Thu Feb 26 03:43:36 2015
From: michael.weylandt at gmail.com (Michael Weylandt)
Date: Wed, 25 Feb 2015 21:43:36 -0500
Subject: [Rd] iterated lapply
In-Reply-To: <54EE4E15.4000506@gmail.com>
References: <4346B4DF-036F-4594-96C0-F8D3121427D0@gmail.com>
	<54EE4E15.4000506@gmail.com>
Message-ID: <D53671B9-C14D-4763-ABA1-79167CCD9113@gmail.com>



> On Feb 25, 2015, at 5:35 PM, Benjamin Tyner <btyner at gmail.com> wrote:
> 
> Actually, it depends on the number of cores:

Under current semantics, yes. Each 'stream' of function calls is lazily capturing the last value of `i` on that core. 

Under Luke's proposed semantics (IIUC),
the result would be the same (2,4,6,8) for both parallel and serial execution. This is what allows for 'drop-in' parallelism. 


>> fun1 <- function(c){function(i){c*i}}
>> fun2 <- function(f) f(2)
>> sapply(mclapply(1:4, fun1, mc.cores=1L), fun2)
>    [1] 8 8 8 8
>> sapply(mclapply(1:4, fun1, mc.cores=2L), fun2)
>    [1] 6 8 6 8
>> sapply(mclapply(1:4, fun1, mc.cores=4L), fun2)
>    [1] 2 4 6 8
> 
>>> / On Feb 24, 2015, at 10:50 AM, <luke-tierney at uiowa.edu <https://stat.ethz.ch/mailman/listinfo/r-devel>> wrote:
>> />/ 
>> />/ The documentation is not specific enough on the indented semantics in
>> />/ this situation to consider this a bug. The original R-level
>> />/ implementation of lapply was
>> />/ 
>> />/    lapply <- function(X, FUN, ...) {
>> />/        FUN <- match.fun(FUN)
>> />/        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]], ...))
>> />/        names(rval) <- names(X)           # keep `names' !
>> />/        return(rval)
>> />/    }
>> />/ 
>> />/ and the current internal implementation is consistent with this. With
>> />/ a loop like this lazy evaluation and binding assignment interact in
>> />/ this way; the force() function was introduced to help with this.
>> />/ 
>> />/ That said, the expression FUN(X[[i]], ...) could be replaced by
>> />/ 
>> />/    local({
>> />/        i <- i
>> />/        list(FUN(X[[i]], ...)
>> />/    })
>> />/ 
>> />/ which would produce the more desirable result
>> />/ 
>> />/    > sapply(test, function(myfn) myfn(2))
>> />/    [1] 2 4 6 8
>> />/ 
>> /
>> Would the same semantics be applied to parallel::mclapply and friends?
>> 
>> sapply(lapply(1:4, function(c){function(i){c*i}}), function(f) f(2))
>> 
>> # [1] 8 8 8 8
>> 
>> sapply(mclapply(1:4, function(c){function(i){c*i}}), function(f) f(2))
>> 
>> # [1] 6 8 6 8
>> 
>> I understand why they differ, but making mclapply easier for 'drop-in' parallelism might be a good thing. 
>> 
>> Michael
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] iterated lapply
Michael Weylandt