I was working with a list of lists today and needed to replace an element of one of the second-level lists. The way to do this seemed obvious, but I realized I wasn't actually clear on why it worked.
Here's an example:
a <- list(aa=list(aaa=1:10,bbb=11:20,ccc=21:30),bb=list(ddd=1:5))
Given this data structure, let's say I want to replace the 3rd element of the nested numeric vector aaa. I could do something like:
newvalue <- 100
a$aa$aaa[3] <- newvalue
Doing this seems obvious enough, but I couldn't explain to myself how this expression actually gets evaluated. Working with the quote function, I cobbled together some rough logic, along the lines of:
(1) Create and submit the top-level function call:
`<-`(a$aa$aaa[3],newvalue)
(2) Lazy evaluation of first argument in (1), call function '[':
`[`(a$aa$aaa,3)
(3) Proceed recursivley down:
`$`(a$aa,"aaa")
(4) ...further down, call '$' again:
`$`(a,"aa")
(5) With (4) returning an actual data structure, proceed back "up the stack" substituting the returned data structures until the actual assignment is made in (1).
I guess my confusion involves some aspects of lazy evaluation and/or evaluation environments. In the example above, I've simply reassigned one element of a vector. But how is it that R keeps track of where that vector is within the greater data structure?
Cheers