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