I am reading Hadley Wickhams's book on Github, in particular this part on lazy evaluation. There he gives an example of consequences of lazy evaluation, in the part with add/adders
functions. Let me quote that bit:
This [lazy evaluation] is important when creating closures with lapply or a loop:
add <- function(x) { function(y) x + y } adders <- lapply(1:10, add) adders[[1]](10) adders[[10]](10)
x is lazily evaluated the first time that you call one of the adder functions. At this point, the loop is complete and the final value of x is 10. Therefore all of the adder functions will add 10 on to their input, probably not what you wanted! Manually forcing evaluation fixes the problem:
add <- function(x) { force(x) function(y) x + y } adders2 <- lapply(1:10, add) adders2[[1]](10) adders2[[10]](10)
I do not seem to understand that bit, and the explanation there is minimal. Could someone please elaborate that particular example, and explain what happens there? I am specifically puzzled by the sentence "at this point, the loop is complete and the final value of x is 10". What loop? What final value, where? Must be something simple I am missing, but I just don't see it. Thanks a lot in advance.
lapply()
has changed in recent R, the functionpurrr::map()
, which is intended to be used whereverlapply()
is, still behaves like the oldlapply()
vis-à-vis shared environments of closures. However, I wouldn't count on this “anachronism” ofpurrr::map()
to stick around, as it will likely be rectified in future versions. – Tillyadders
andadders2
's outputs! – Communist