On 12-04-24 7:34 PM, Ali Tofigh wrote:
Many thanks to both Duncan and Bert for clarifying this. Having looked
carefully at what you both wrote, my conclusion is the following:

in this code below

f<- function(x) {function() {x}}
b<- lapply(1:3, f)

lapply does not actually call f with the values 1, 2, and 3. Instead,
it calls f three times with the same object that, had only f used x
for something, would have evaluated to 1 in the first call and to 2 in
the second etc. but since f does not use x, the expression passed to f
is never actually evaluated until the first time one of the functions
in b is called. But at that point, that object will evaluate to 3 for
all three functions in b.

so what lapply is doing resembles:

z<- 1; i<- f(z); z<-2; j<- f(z); z<- 3; k<- f(z); b<- list(i, j, k)
b[[1]]()
[1] 3
b[[2]]()
[1] 3
b[[3]]()
[1] 3

Yes, I think that's exactly right.

Duncan Murdoch


Thanks again!
/Ali

On Tue, Apr 24, 2012 at 18:37, Duncan Murdoch<murdoch.dun...@gmail.com>  wrote:
On 12-04-24 5:13 PM, Ali Tofigh wrote:

On Tue, Apr 24, 2012 at 16:57, Duncan Murdoch<murdoch.dun...@gmail.com>
  wrote:

I thought that
lapply calls f three times and returns a list with whatever f
returned. Is this not so?


That is so.  In each case, f creates a function that looks in its
enclosing
environment for the variable x to be returned.

That enclosing environment is the evaluation frame of f, where x is the
argument being passed.

But x is never used in evaluating f, so the promise to evaluate x is
never
forced until you finally call one of those functions.

That means x will refer to some internal variable in lapply (which sapply
calls).  You'll have 3 different promises to evaluate it, but they all
evaluate to the same value.


Thank you Duncan for you reply! However, I'm not sure I understand
this last explanation. This is what I think you mean lapply does.
Pleas correct me if I'm wrong.

1) lapply uses the same variable name as the argument in my function
(in this case 'x')


No, lapply can use any name it likes, or no name at all (e.g. just an
expression like 1+y).


2) lapply uses this 'x' variable to set up a bunch of unevaluated calls


No, lapply calls f a bunch of times, passing this expression each time.


3) finally, lapply evaluates all the calls. but at this point,
lapply's 'x' variable is set to the last element of the list that was
passed to it and all the unevaluated calls will now use this value as
their 'x'?


When lapply evaluates f, it produces a function that refers to the local
variable x in each evaluation frame.  That's a different variable each time,
but in all cases it's a promise to evaluate the expression that lapply
passed in.  So if lapply passed 1+y as the expression, x becomes a promise
to evaluate 1+y in lapply's evaluation frame.

Since you don't call any of those functions until after lapply is done, its
evaluation frame will remain.  It's hard to get to it, but each of those
promises references it.

When you finally evaluate x in one of those functions, it goes and evaluates
1+y in the lapply frame (or whatever the expression was). That evaluates to
3.  It could have evaluated to 17 if lapply had done something stupid like
setting y to 16 after calling f in the loop, but R functions never do stupid
things, so you don't need to worry about that.

Duncan Murdoch

______________________________________________
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.

Reply via email to