tom wright
2005-Nov-15 12:35 UTC
[R] changing the value of a variable from inside a function
Michael,
I feel sure people are going to come up with other better suggestions
here but does <- work for you?
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)
}
On Tue, 2005-15-11 at 12:22 -0500, Michael Wolosin
wrote:> 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
Michael Wolosin
2005-Nov-15 17:22 UTC
[R] changing the value of a variable from inside a function
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. 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
Gabor Grothendieck
2005-Nov-15 18:16 UTC
[R] changing the value of a variable from inside a function
Use eval.parent as shown in example 1. Note that you might
be tempted to use example 2 but it does not actually fulfill
the letter of the original post since it changes test in the lexical
environment of f, i.e.the environment where f is defined,
rather than the calling frame of f, i.e. the environment from where
f is called. To get <<- to work with example 2 we must
create a new f that is the same as the original f but whose
lexical environment has been changed to be the caller frame
as shown in example 3.
# example 1. ok. test changed in caller frame.
test <- 11:13
f <- function(i) eval.parent(substitute(test[i] <- 99))
g <- function() { test <- 1:3; f(2); print(test) }
g() # 1 99 3
test # 11 12 13
# example 2. Same except f has been changed.
# Note that this changes test in the lexical environment
# rather than in the caller frame.
test <- 11:13
f <- function(i) test[i] <<- 99
g <- function() { test <- 1:3; f(2); print(test) }
g() # 1 2 3
test # 11 99 13
# example 3. same as example 2 but the lexical environment of f is
# forced to be the caller frame so that it works as in example 1.
# f is the same as in example 1 and g has been changed to
# create a new f like the original f but with the caller frame as its
# lexical environment.
test <- 11:13
f <- function(i) test[i] <<- 99
g <- function() { test <- 1:3; environment(f) <- environment(); f(2);
print(test) }
g() # 1 99 3
test # 11 12 13
Another possibility, which is similar in effect to example 1, would be
to use defmacro in package gtools.
On 11/15/05, Michael Wolosin <msw10 at duke.edu>
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. 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
>
Feng Tai
2005-Nov-15 19:21 UTC
[R] changing the value of a variable from inside a function
You could use 'ref' package. Feng>From: Michael Wolosin <msw10 at duke.edu> >To: r-help at stat.math.ethz.ch >Subject: [R] changing the value of a variable from inside a function >Date: Tue, 15 Nov 2005 12:22:15 -0500 > >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. 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
Duncan Murdoch
2005-Nov-17 14:39 UTC
[R] changing the value of a variable from inside a function
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 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