My question is a seemingly simple one. I have a bunch of user-defined functions which compute such-and-such objects. I want to be able to define a variable in a particular function, then make use of it later, perhaps in a different function, without necessarily having to move it around in argument lists. In the C community, it would be called a "global" variable. Question 1: Is this practical at all in the R language? Suppose the variable is called x23. I want to assign a value to it, then use it later. Seemingly, there are two cases: Case I is if the variable is given its value at the top level. Case II is if it is given its value inside a user-defined function. That I do not know how to do. Example: func1 <- function (){ x23 <- 2.6 return () } driver_func <- function (){ func1 () print (x23) return () } However, when I call driver_func, it won't work. Beginning with the load operation, I get: ---------------------------------------------------------------- Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R.> func1 <- function (){+ + x23 <- 2.6 + + return () + + }> > driver_func <- function (){+ + func1 () + + print (x23) + + return () + + }> driver_func ()Error in print(x23) : object "x23" not found>--------------------------------------------------------------------------->From Tom:Clearly, the two functions cannot communicate. I am aware of the existence of environments, but don't know much about them. Also, the attach function and the get and set functions. Also, .GlobalEnv It might or might not make sense to create a list of "all" of the variables, with two functions which get all of them and set all of them. The function calls may be thought of as an upside down tree. I want to be able to communicate from any node to any other node. Your advice? Tom Thomas L. Jones, PhD, Computer Science
Thomas L Jones wrote:> > My question is a seemingly simple one. I have a bunch of user- > defined functions which compute such-and-such objects. I want to be > able to define a variable in a particular function, then make use of > it later, perhaps in a different function, without necessarily > having to move it around in argument lists. In the C community, it > would be called a "global" variable. >Global variables in R are used with <<- instead of <-. For example: x <- 1 y <- 1 f <- function() { x <- 2 y <<- 2 } f() will turn y to 2 but will not change x. Alberto Monteiro
Global variables are strongly discouraged in R, but there are sometimes when they may be needed and so are possible. One example where they are used is in random number generation, every time a random number function is called (rnorm for example) the "global" variable .Random.seed is updated so that new random values will be generated next time. If you absolutely need a global variable, then use assign (or possibly <<-) to do the assignment. Also choose a name such that your global variable is unlikely to overwright or be overwritten (if you use x, then both are likely to happen, preferable to use a name starting with '.'). A better approach is to use variables in a local environment such that the 2 functions can both see the variable, but nothing outside of that environment can. Here is a simple example:> tmp <- local({+ x23 <- numeric(1) + func1 <- function(){ + x23 <<- 2.6 + } + func2 <- function(){ + print(x23) + } + list(func1=func1,func2=func2) + })> > func1 <- tmp$func1 > func2 <- tmp$func2 > > func2()[1] 0> func1() > func2()[1] 2.6> tmp$func2()[1] 2.6>The local function creates a new environment in which everything in the {} is evaluated/created. This new environment then gets a variable (x23) which starts off to be 0. The 2 functions defined in the same environment can access x23. The list statement just combines the 2 functions into a single object to be returned. So after running local, the variable tmp is a list with 2 elements each being a function, we can run them as tmp$func2() or copy them to easier to use functions. We run func2 and see that x23 is currently 0, then run func1 to change the value (don't see anything yet) then run func2 again to see the new value of x23. This is a cleaner solution in that if we already have a variable called x23, it does not get overwritten by the "global" and it is very difficult to accidentally overwrite the x23 shared by the 2 functions. Hope this helps, -- Gregory (Greg) L. Snow Ph.D. Statistical Data Center Intermountain Healthcare greg.snow at intermountainmail.org (801) 408-8111> -----Original Message----- > From: r-help-bounces at r-project.org > [mailto:r-help-bounces at r-project.org] On Behalf Of Thomas L Jones, PhD > Sent: Monday, November 26, 2007 10:11 AM > To: R-project help > Subject: [R] Communicating from one function to another > > My question is a seemingly simple one. I have a bunch of > user-defined functions which compute such-and-such objects. I > want to be able to define a variable in a particular > function, then make use of it later, perhaps in a different > function, without necessarily having to move it around in > argument lists. In the C community, it would be called a > "global" variable. > > Question 1: Is this practical at all in the R language? > > Suppose the variable is called x23. I want to assign a value > to it, then use it later. Seemingly, there are two cases: > > Case I is if the variable is given its value at the top level. > > Case II is if it is given its value inside a user-defined > function. That I do not know how to do. > > Example: > > func1 <- function (){ > > x23 <- 2.6 > > return () > > } > > driver_func <- function (){ > > func1 () > > print (x23) > > return () > > } > > However, when I call driver_func, it won't work. Beginning > with the load operation, I get: > > ---------------------------------------------------------------- > > Type 'demo()' for some demos, 'help()' for on-line help, or > 'help.start()' for an HTML browser interface to help. > Type 'q()' to quit R. > > > func1 <- function (){ > + > + x23 <- 2.6 > + > + return () > + > + } > > > > driver_func <- function (){ > + > + func1 () > + > + print (x23) > + > + return () > + > + } > > driver_func () > Error in print(x23) : object "x23" not found > > > > -------------------------------------------------------------- > ------------- > >From Tom: > > Clearly, the two functions cannot communicate. I am aware of > the existence of environments, but don't know much about > them. Also, the attach function and the get and set > functions. Also, .GlobalEnv It might or might not make sense > to create a list of "all" of the variables, with two > functions which get all of them and set all of them. The > function calls may be thought of as an upside down tree. I > want to be able to communicate from any node to any other node. > > Your advice? > > Tom > Thomas L. Jones, PhD, Computer Science > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Others have already answered your direct question but consider that what you may want without realizing it is object-oriented programming. Here p is a proto object with components x and f. x is a variable and f is a method. The method f sets x to a. (Presumably in reality f would do other things too but for this example that's all it does.) Before invoking f, x is 0 and after invoking f x is 3. Lastly we invoke method g on proto object p and get back 30. library(proto) p <- proto(x = 0, f = function(., a) .$x <- a, g = function(.) .$x * 10) p$x # 0 p$f(3) p$x # 3 p$g() # 30 See: http:/r-proto.googlecode.com for more. On Nov 26, 2007 12:11 PM, Thomas L Jones, PhD <jones3745 at verizon.net> wrote:> My question is a seemingly simple one. I have a bunch of user-defined > functions which compute such-and-such objects. I want to be able to define a > variable in a particular function, then make use of it later, perhaps in a > different function, without necessarily having to move it around in argument > lists. In the C community, it would be called a "global" variable. > > Question 1: Is this practical at all in the R language? > > Suppose the variable is called x23. I want to assign a value to it, then use > it later. Seemingly, there are two cases: > > Case I is if the variable is given its value at the top level. > > Case II is if it is given its value inside a user-defined function. That I > do not know how to do. > > Example: > > func1 <- function (){ > > x23 <- 2.6 > > return () > > } > > driver_func <- function (){ > > func1 () > > print (x23) > > return () > > } > > However, when I call driver_func, it won't work. Beginning with the load > operation, I get: > > ---------------------------------------------------------------- > > Type 'demo()' for some demos, 'help()' for on-line help, or > 'help.start()' for an HTML browser interface to help. > Type 'q()' to quit R. > > > func1 <- function (){ > + > + x23 <- 2.6 > + > + return () > + > + } > > > > driver_func <- function (){ > + > + func1 () > + > + print (x23) > + > + return () > + > + } > > driver_func () > Error in print(x23) : object "x23" not found > > > > --------------------------------------------------------------------------- > >From Tom: > > Clearly, the two functions cannot communicate. I am aware of the existence > of environments, but don't know much about them. Also, the attach function > and the get and set functions. Also, .GlobalEnv It might or might not make > sense to create a list of "all" of the variables, with two functions which > get all of them and set all of them. The function calls may be thought of as > an upside down tree. I want to be able to communicate from any node to any > other node. > > Your advice? > > Tom > Thomas L. Jones, PhD, Computer Science