0

This is an example from Hadley's latest book (Advanced R). I hope he does not mind that I posted it.

I am having difficulty to understand why this code snippet does what it does. Could someone expand on this? How can I divide it into mini steps?

add <- function(x) {

    function(y) x+y
}

adders <- lapply(1:10,add)

I understand a simpler call to "add" function.

> add(2)(1)

[1] 3

In a way, 2 is assigned to x and 1 is assigned to y.

When we use this function with lapply (this way), how does y get assigned a value?

thelatemail
  • 91,185
  • 12
  • 128
  • 188
user2649059
  • 143
  • 1
  • 6
  • Well, that's weird -- all 10 functions in adders are the same: `function(y) 10+y`. Try `sapply(adders,function(z) \`z\`(1))` That doesn't seem to be your question, though; I don't even know what your question means. `y` is *not* assigned a value in your `lapply` call. Your function returns a function. – Frank Feb 17 '15 at 00:11
  • 2
    This is explained as a case of "lazy evaluation" by Hadley here: https://github.com/hadley/adv-r/blob/master/Functions.rmd#lazy-evaluation-lazy-evaluation – thelatemail Feb 17 '15 at 00:17

1 Answers1

1

This doesn't do quite what you first think. Intuition suggests that the call to lapply would return a list of functions which add 1, 2, 3, ..., 10 to their argument.

In fact, lapply(1:10,add) returns a list of functions, each of which adds 10 to their argument.

In the console, I tried a simpler version

> v<-lapply(1:3, add)
> v
[[1]]
function (y) 
x + y
<environment: 0x28b0540>

[[2]]
function (y) 
x + y
<environment: 0x28af678>

[[3]]
function (y) 
x + y
<environment: 0x28af800>
> v[[1]](1)
[1] 4
> v[[2]](1)
[1] 4
> v[[3]](1)
[1] 4
> 

It's hard to see the use of this result.

kdopen
  • 8,032
  • 7
  • 44
  • 52
  • While interesting, this isn't really an answer to the question. – thelatemail Feb 17 '15 at 00:23
  • 1
    In the book, it mentions that add <- function(x) { force(x) function(y) x+y }, adding "force(x)" would give us what we intuitively expect. Without force(x), the code adds 10 (and it is still little confusing to me). The book suggests it is the end of loop, and 10 is the last value of X. – user2649059 Feb 17 '15 at 00:24
  • Including a `print(x)` inside `add` shows you how it's called ... but also changes the outcome as it forces the evaluation of `x` to happen during the call to add. – kdopen Feb 17 '15 at 00:24