Murat Tasan
2013-Aug-14 23:47 UTC
[Rd] local variable assignment: first copies from higher frame?
hi all -- this might not be the correct list for this
question/discussion, though R-help didn't seem like the correct venue,
either, so...
i'm looking for just some extra clarification of how local variables
are defined/bound, beyond the simple cases given in the Language
document.
the particular instance is when there is variable assignment inside a function.
normally, this creates a local variable, but there appears to be an
additional preceding step that does a bit more: the local variable is
initialized to the value of any same-named variable bound in a
containing frame.
in a sense, the lexical scoping rule is first applied to acquire a
value, and this value is then applied to the new local variable, and
is then immediately changed by the assignment operation.
i only noticed this when assigning variables to entries within a
'list' structure, like so:
tempf <- function(x, local = TRUE)
{
executing_environment <- environment()
closure_environment <- parent.env(executing_environment)
print(executing_environment)
cat(str(mget("my_list", envir = executing_environment, inherits
FALSE, ifnotfound = NA)[[1]]))
print(closure_environment)
cat(str(mget("my_list", envir = closure_environment, inherits
FALSE, ifnotfound = NA)[[1]]))
if(local) {
my_list$x <- x
} else {
my_list$x <<- x
}
print(executing_environment)
cat(str(mget("my_list", envir = executing_environment, inherits
FALSE, ifnotfound = NA)[[1]]))
print(closure_environment)
cat(str(mget("my_list", envir = closure_environment, inherits
FALSE, ifnotfound = NA)[[1]]))
}
> my_list <- list(x = 1, y = 2)
> tempf(0, local = TRUE)
<environment: 0xcb47cb8>
logi NA
<environment: R_GlobalEnv>
List of 2
$ x: num 1
$ y: num 2
<environment: 0xcb47cb8>
List of 2
$ x: num 0
$ y: num 2
<environment: R_GlobalEnv>
List of 2
$ x: num 1
$ y: num 2> tempf(0, local = FALSE)
<environment: 0xbf4df50>
logi NA
<environment: R_GlobalEnv>
List of 2
$ x: num 1
$ y: num 2
<environment: 0xbf4df50>
logi NA
<environment: R_GlobalEnv>
List of 2
$ x: num 0
$ y: num 2
what surprised me in the first "local = TRUE" case is that 'y'
is
still 2 in the executing environment.
so, i think my question comes down to this: when a new local variable
is created in an assignment operation, is the full value of any
matching variable in a containing frame first copied to the new local
variable?
and if so, was this chosen as a strategy specifically to allow for
these sorts of "indexed" assignment operations? (where i'm
assigning
to only a single location within the vector object)?
and finally, are the other entries in the vector fully copied over, or
are they treated as "promises" similar to formal parameters, albeit
now as single entries within a containing vector?
thanks for any help on digging down a bit on the implementation here!
-murat
Peter Meilstrup
2013-Aug-15 02:19 UTC
[Rd] local variable assignment: first copies from higher frame?
Not anything that complicated -- your answer is in the R language definition under 'Subset assignment' and the part in "Function calls" that describes assignment functions. Whenever a call is found on the left side of a `<-`, it is munged by sticking a "<-" on the function name and pulling out the first argument. So my_list$x <- x which is syntactically equivalent to `$`(my_list, x) <- x is effectively transformed into something like: my_list <- `$<-`(my_list, x, x) The function `$<-` gets its argument from wherever it is found, and returns a modified version. Peter [[alternative HTML version deleted]]