Wacek, I think when people say that R semantics are derived from Scheme, all they mean is that R supports lexical closures. But R has other features which are very un-Scheme-like, and when they interact with lexical closures, you get behavior you don't find in other functional languages.
R passes function arguments using a "promise" mechanism somewhat similar to Algol 60's call-by-name, but caching the result when it is evaluated, what is sometimes called call-by-need. If the argument value is not needed, it keeps it as a "promise" (what Algol 60 called a "thunk"). Thus, we have: lapply(1:5,function(i) function( ) i )[[1]]() => 5 since the inner i is actually bound to a 'promise' which seems to point to the variable used by lapply for counting. Compare with the result of: lapply(1:5,function(i) { i<-i; function() i } )[[1]]() => 1 Scheme of course does not have the "promise" mechanism so this doesn't happen. I'm new to R, so I don't know if this is considered a bug or a feature. -s On Mon, Nov 17, 2008 at 4:28 PM, Wacek Kusnierczyk <[EMAIL PROTECTED]> wrote: > the following is a trivialized version of some functional code i tried > to use in r: > > (funcs = lapply(1:5, function(i) function() i)) > # a list of no-parameter functions, each with its own closure environment, > # each supposed to return the corresponding index when applied to no > arguments > > sapply(funcs, function(func) func()) > # supposed to return c(1,2,3,4,5) > > there is absolutely nothing unusual in this code, in the context of > functional programming. > the following is my best translation to python (modulo indexing, which > is inessential), where it does what i wanted: > > funcs = map(lambda i: lambda: i, range(5)) > map(lambda func: func(), funcs) > # [0,1,2,3,4] > > all these functions have distinct environments: > > (envs = sapply(funcs, function(func) environment(func))) > assign("i", 0, environment(envs[[1]])) > sapply(funcs, function(func) func()) > > interestingly, identical says they are all unequal, but compare disagrees. > > check = function(equal) for (i in 1:4) for (j in i:4+1) > print(equal(envs[[i]], envs[[j]])) > check(identical) > check(compare) > > compare seems to cast environments to character; for identical, the docs > give an example where environments are compared, but compare fails > (i.e., succeeds) miserably (the docs do not warn not to compare > environments): > > e1 = new.env(parent=emptyenv()) > e2 = new.env(parent=emptyenv()) > assign("foo", "bar", e1) > compare(e1, e2) > # oops? > > > back to the original example, how come? > > vQ > > > ---- > for those curious, try the following in python: > > map(lambda func: func(), [lambda: i for i in range(5)]) > map(lambda func: func(), (lambda: i for i in range(5))) > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.