Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promises in lapply / R

I am not sure what the promises are doing in R

If one runs

a = lapply(seq_len(2), function(n) { function() {n}})
b = lapply(seq_len(2), function(n)  {n})

we can see that

a[[1]]() # == 2
b[[1]]   # == 1

I understand that R uses promise's object and lazily evaluates an expression in its environment, but I dont understand why the different environments created for each function would not contain their own value for n.

[[1]]
function () 
{
    n
}
<environment: 0x7f9b2416ad18>

[[2]]
function () 
{
    n
}
<environment: 0x7f9b2416ab20>

as.list(environment(a[[1]])) 
$n
[1] 2

as.list(environment(a[[2]]))
$n
[1] 2

Is it be possible to fix the semantic through the lapply function somehow ?

lapply
function (X, FUN, ...) 
{
    FUN <- match.fun(FUN)
    if (!is.vector(X) || is.object(X)) 
        X <- as.list(X)
    .Internal(lapply(X, FUN))
}
<bytecode: 0x7f9b25150f18>
<environment: namespace:base>

PS : refocused question

Edit : concretely, is it possible to write a lapply2 function that generically "forces" the argument to have uniform behaviour as in :

pl <- lapply (1:3, function(y) { force(y); function(x) pow(x,y) } )
pl <- lapply2(1:3, function(y) { function(x) pow(x,y) } )
like image 357
nicolas Avatar asked Oct 22 '22 06:10

nicolas


1 Answers

I find it easier to understand in this form:

f=function(n) {function() {n}}
x=1
a=f(x)
x=2
a()
[1] 2

The key part of the documentation is

When a function is called the arguments are matched and then each of the formal arguments is bound to a promise. The expression that was given for that formal argument and a pointer to the environment the function was called from are stored in the promise.

After the call a=f(x), the function argument n is bound to a promise with the name x and a pointer to the global environment .GlobalEnv.

In your lapply examples, the anonymous function function(n) { function() {n}} is called from the global environment each time. This is why every element of the list a gets the same value of n: it's coming from the global environment. I don't see how it's possible to change this behaviour by rewriting lapply.

like image 179
Alexander Hanysz Avatar answered Nov 03 '22 04:11

Alexander Hanysz