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

The C implementation could use this approach, or could rebuild the
expression being evaluated at each call to get almost the same semantics.
Both would add a little overhead. Some code optimization might reduce
the overhead in some instances (e.g. if FUN is a BUILTIN), but it's
not clear that would be worth while.

Variants of this issue arise in a couple of places so it may be worth
looking into.

Best,

luke

On Tue, 24 Feb 2015, Radford Neal wrote:

From: Daniel Kaschek <daniel.kasc...@physik.uni-freiburg.de>
... When I evaluate this list of functions by
another lapply/sapply, I get an unexpected result: all values coincide.
However, when I uncomment the print(), it works as expected. Is this a
bug or a feature?

conditions <- 1:4
test <- lapply(conditions, function(mycondition){
  #print(mycondition)
  myfn <- function(i) mycondition*i
  return(myfn)
})

sapply(test, function(myfn) myfn(2))

From: Jeroen Ooms <jeroeno...@gmail.com>
I think it is a bug. If we use substitute to inspect the promise, it
appears the index number is always equal to its last value:

From: Duncan Temple Lang <dtemplel...@ucdavis.edu>
Not a bug, but does surprise people. It is lazy evaluation.


I think it is indeed a bug.  The lapply code saves a bit of time by
reusing the same storage for the scalar index number every iteration.
This amounts to modifying the R code that was used for the previous
function call.  There's no justification for doing this in the
documentation for lapply.  It is certainly not desired behaviour,
except in so far as it allows a slight savings in time (which is
minor, given the time that the function call itself will take).

  Radford Neal

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
   Actuarial Science
241 Schaeffer Hall                  email:   luke-tier...@uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to