So, I've been confused by this for a while. If I want to create functions in an apply, it only uses the desired value for the variable if I create a new local variable:> lapply(1:5,function(h){k=h;function(){k}})[[1]]()[1] 1> lapply(1:5,function(k){function(){k}})[[1]]()[1] 5>Normally, a function will use values for a variable if the variable is local to the definition of the function:> a = function(x){function(){x}} > a(5)function(){x}> a(5)()[1] 5> a(6)()[1] 6 So why doesn't this work for apply? Does apply work more like loops, with a shared variable that changes values so that the first function defined actually uses the last value of the variable?> a = list();for (k in 1:5){a = c(a,function(){k})} > a[[1]]()[1] 5>Or is there something else entirely? -- View this message in context: http://r.789695.n4.nabble.com/Scope-and-apply-type-functions-tp3385230p3385230.html Sent from the R help mailing list archive at Nabble.com.
Hi,
I think it's a side effect of lazy evaluation, where you should
probably use the ?force like a jedi,
lapply(1:5,function(k){force(k) ; function(){k}})[[2]]()
HTH,
baptiste
On 18 March 2011 07:01, jamie.f.olson <inspired2apathy at gmail.com>
wrote:> So, I've been confused by this for a while. ?If I want to create
functions in
> an apply, it only uses the desired value for the variable if I create a new
> local variable:
>
>> lapply(1:5,function(h){k=h;function(){k}})[[1]]()
> [1] 1
>> lapply(1:5,function(k){function(){k}})[[1]]()
> [1] 5
>>
>
> Normally, a function will use values for a variable if the variable is
local
> to the definition of the function:
>
>> a = function(x){function(){x}}
>> a(5)
> function(){x}
>
>> a(5)()
> [1] 5
>> a(6)()
> [1] 6
>
>
> So why doesn't this work for apply? ?Does apply work more like loops,
with a
> shared variable that changes values so that the first function defined
> actually uses the last value of the variable?
>
>> a = list();for (k in 1:5){a = c(a,function(){k})}
>> a[[1]]()
> [1] 5
>>
>
>
> Or is there something else entirely?
>
> --
> View this message in context:
http://r.789695.n4.nabble.com/Scope-and-apply-type-functions-tp3385230p3385230.html
> Sent from the R help mailing list archive at Nabble.com.
>
> ______________________________________________
> R-help at 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.
>
Try this:
lapply(1:5,function(i){i;function()i})[[2]]()
or
lapply(1:5,function(i){i;function(j=i) j } )[[2]]()
## both give 2
Now try:
lapply(1:5,function(i){function(j=i) j } )[[2]]()
## gives 5 !
The problem is that if you do:
lapply(1:5,function(h){function(h)h)
what you get is a list of functions of the form function(h)h , where the
The "h" in this function has nothing to do with the index
"h" in the
lapply statement, which no longer exists. So the result is an error
message saying it can't find h.
The top 2 versions specifically put the value of i at the time the ith
function is defined into the function environment, so they exist after
the lapply call is finished.
The 3rd version obviously uses the value of i at the conclusion of the
lapply call when the list of functions is returned from the lapply
call and they need to find the value of i for their environments.
In general, the scoping with lapply gets complicated and, iirc, the
experts have said is nonstandard (Experts: please correct if wrong).
So the best advice is to try to avoid constructs like this if
possible.
-- Bert
On Thu, Mar 17, 2011 at 11:01 AM, jamie.f.olson
<inspired2apathy at gmail.com> wrote:> So, I've been confused by this for a while. ?If I want to create
functions in
> an apply, it only uses the desired value for the variable if I create a new
> local variable:
>
>> lapply(1:5,function(h){k=h;function(){k}})[[1]]()
> [1] 1
>> lapply(1:5,function(k){function(){k}})[[1]]()
> [1] 5
>>
>
> Normally, a function will use values for a variable if the variable is
local
> to the definition of the function:
>
>> a = function(x){function(){x}}
>> a(5)
> function(){x}
>
>> a(5)()
> [1] 5
>> a(6)()
> [1] 6
>
>
> So why doesn't this work for apply? ?Does apply work more like loops,
with a
> shared variable that changes values so that the first function defined
> actually uses the last value of the variable?
>
>> a = list();for (k in 1:5){a = c(a,function(){k})}
>> a[[1]]()
> [1] 5
>>
>
>
> Or is there something else entirely?
>
> --
> View this message in context:
http://r.789695.n4.nabble.com/Scope-and-apply-type-functions-tp3385230p3385230.html
> Sent from the R help mailing list archive at Nabble.com.
>
> ______________________________________________
> R-help at 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.
>