[R] changing the value of a variable from inside a function

Duncan Murdoch murdoch at stats.uwo.ca
Thu Nov 17 16:53:45 CET 2005


On 11/17/2005 9:39 AM, Duncan Murdoch wrote:
> On 11/15/2005 12:22 PM, Michael Wolosin wrote:
>> All -
>> 
>> I am trying to write R code to implement a recursive algorithm.  I've 
>> solved the problem in a klunky way that works, but uses  more memory and 
>> computing time than it should.
>> 
>> A more elegant solution than my current one would require updating the 
>> values of a variable that is located in what I will call the "root" 
>> environment - that environment from which the original call to the 
>> recursive function was issued.  
> 
> That's tricky and ugly, but possible in various ways.  However, the 
> clean easy way to do this is to wrap your recursive function in a 
> non-recursive one, and refer to variables in the non-recursive one using 
> lexical scoping.  For example,
> 
> wrapper <- function(test) {
>     test <- test  # make a copy in the wrapper environment

Whoops, as Martin Maechler pointed out to me, this line is unnecessary. 
  The fact that test is an argument to wrapper means that a local copy 
would have been made already.

(I am fairly sure this line wouldn't cost very much, since R would 
recognize that a third copy of test isn't needed, but I shouldn't have 
put it there.)

Duncan Murdoch

>     blah <- function() {
>         # references here to test will see the one in wrapper
>         # blah can call itself; each invocation will see the same test
> 
>         test[i,] <<- expr  #  use "super-assignment" to modify it
>     }
>     return(test)
> }
> 
> This makes one copy of the matrix and works on that.  If you want to 
> make zero copies, you need to get tricky.
> 
> Duncan Murdoch
> 
> Certainly, I could pass the variable into
>> the function, update it inside, and return it.  However, the variable I am 
>> updating is a large matrix, and the recursion could end up several hundred 
>> levels deep.  Passing the matrix around would create a copy in the 
>> environment for each call, wasting memory, time, and space.
>> 
>> I've read the help on the "sys.{}" family of functions, and "eval", and 
>> although I can't claim to have absorbed it all, it seems like it is much 
>> easier to access the value of a variable in a parent frame than it is to 
>> update that value with assignment.
>> If you make an assignment inside a function, even if it is to a section of 
>> a variable that exists in a parent frame, the variable is only created or 
>> updated in the current environment - never in the parent frame.
>> 
>> For example:
>> 
>> test <- matrix(NA,nrow=4,ncol=3)
>> test[1,] <- c(1,2,3)
>> blah <- function(i){
>>    test[i,] <- c(0,1,2) + i
>>    return(test)
>> }
>> test
>> blah(2)
>> test
>> 
>> So the real question is, how do I write the function like "blah" above that 
>> updates "test" in the parent or root frame?
>> 
>> blah <- function(i){
>>    test[i,] <- c(1,2,3) + i  #modify this line somehow
>>    return(NULL)
>> }
>> If done "correctly", we will get:
>>  > blah(2)
>>  > test
>>        [,1] [,2] [,3]
>>   [1,]    1    2    3
>>   [2,]    2    3    4
>>   [3,]   NA   NA   NA
>>   [4,]   NA   NA   NA
>> 
>> And given an example that works from within a single function call, does it 
>> have to be modified to work recursively?
>> 
>> blah <- function(i){
>>    if (i<4) {blah(i + 1)}
>>    test[i,] <- c(0,1,2) + i  #modify this line somehow
>>    return(NULL)
>> }
>> If written "correctly", the following would be the output:
>>  > blah(2)
>>  > test
>>        [,1] [,2] [,3]
>>   [1,]    1    2    3
>>   [2,]    2    3    4
>>   [3,]    3    4    5
>>   [4,]    4    5    6
>> 
>> One idea would be to write out to a file.  The filename could reside in the 
>> root environment, and that is all that is needed.  But  this also seems 
>> inelegant (and slow).  If I can read and write to a file, I should be able 
>> to read and write to a memory location.
>> 
>> I suspect that the solution lies somewhere in the "sys" functions, but I 
>> was having trouble seeing it.  Any help would be appreciated.
>> 
>> Thank you in advance,
>> 
>> Mike
>> 
>> ______________________________________________
>> R-help at stat.math.ethz.ch mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
> 
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html




More information about the R-help mailing list