John C Nash
2012-Apr-05 20:20 UTC
[R] Appropriate method for sharing data across functions
In trying to streamline various optimization functions, I would like to have a scratch pad of working data that is shared across a number of functions. These can be called from different levels within some wrapper functions for maximum likelihood and other such computations. I'm sure there are other applications that could benefit from this. Below are two approaches. One uses the <<- assignment to a structure I call OPCON. The other attempts to create an environment with this name, but fails. Though I have looked at a number of references, I have so far not found an adequate description of how to specify where the OPCON environment is located. (Both the green and blue books do not cover this topic, at least not under "environment" in the index.) Is there a recommended approach to this? I realize I could use argument lists, but they get long and tedious with the number of items I may need to pass, though passing the OPCON structure in and out might be the proper way. An onAttach() approach was suggested by Paul Gilbert and tried, but it has so far not succeeded and, unfortunately, does not seem to be usable from source() i.e., cannot be interpreted but must be built first. JN Example using <<- rm(list=ls()) optstart<-function(npar){ # create structure for optimization computations # npar is number of parameters ?? test?? OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, KFN=0, KGR=0, KHESS=0) # may be other stuff ls(OPCON) } add1<-function(){ OPCON$KFN<<-1+OPCON$KFN test<-OPCON$KFN } OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, KFN=0, KGR=0, KHESS=0) ls(OPCON) print(add1()) print(add1()) print(ls.str()) rm(OPCON) # Try to remove the scratchpad print(ls()) tmp<-readline("Now try from within a function") setup<-optstart(4) # Need to sort out how to set this up appropriately cat("setup =") print(setup) print(add1()) print(add1()) rm(OPCON) # Try to remove the scratchpad =====================Example (failing) using new.env: rm(list=ls()) optstart<-function(npar){ # create structure for optimization computations # npar is number of parameters ?? test?? OPCON<-new.env(parent=globalenv()) OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, KFN=0, KGR=0, KHESS=0) # may be other stuff ls(OPCON) } add1<-function(){ OPCON$KFN<-1+OPCON$KFN test<-OPCON$KFN } OPCON<-new.env(parent=globalenv()) OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, KFN=0, KGR=0, KHESS=0) ls(OPCON) print(add1()) print(add1()) print(ls.str()) rm(OPCON) # Try to remove the scratchpad print(ls()) tmp<-readline("Now try from within a function") setup<-optstart(4) # Need to sort out how to set this up appropriately cat("setup =") print(setup) print(add1()) print(add1()) rm(OPCON) # Try to remove the scratchpad
Hadley Wickham
2012-Apr-05 20:32 UTC
[R] Appropriate method for sharing data across functions
Why not pass around a reference class? Hadley On Thu, Apr 5, 2012 at 3:20 PM, John C Nash <nashjc at uottawa.ca> wrote:> In trying to streamline various optimization functions, I would like to have > a scratch pad of working data that is shared across a number of functions. > These can be called from different levels within some wrapper functions for > maximum likelihood and other such computations. I'm sure there are other > applications that could benefit from this. > > Below are two approaches. One uses the <<- assignment to a structure I call > OPCON. The other attempts to create an environment with this name, but > fails. Though I have looked at a number of references, I have so far not > found an adequate description of how to specify where the OPCON environment > is located. (Both the green and blue books do not cover this topic, at least > not under "environment" in the index.) > > Is there a recommended approach to this? I realize I could use argument > lists, but they get long and tedious with the number of items I may need to > pass, though passing the OPCON structure in and out might be the proper way. > An onAttach() approach was suggested by Paul Gilbert and tried, but it has > so far not succeeded and, unfortunately, does not seem to be usable from > source() i.e., cannot be interpreted but must be built first. > > JN > > Example using <<- > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > ? # npar is number of parameters ?? test?? > ? OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > ? ? ? KFN=0, KGR=0, KHESS=0) > ? # may be other stuff > ? ls(OPCON) > } > > add1<-function(){ > ? OPCON$KFN<<-1+OPCON$KFN > ? test<-OPCON$KFN > } > > OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > ? ? ? KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > =====================> Example (failing) using new.env: > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > ? # npar is number of parameters ?? test?? > ? OPCON<-new.env(parent=globalenv()) > ? OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > ? ? ? KFN=0, KGR=0, KHESS=0) > ? # may be other stuff > ? ls(OPCON) > } > > add1<-function(){ > ? OPCON$KFN<-1+OPCON$KFN > ? test<-OPCON$KFN > } > > OPCON<-new.env(parent=globalenv()) > OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > ? ? ? KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > ______________________________________________ > 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.-- Assistant Professor / Dobelman Family Junior Chair Department of Statistics / Rice University http://had.co.nz/
William Dunlap
2012-Apr-06 01:17 UTC
[R] Appropriate method for sharing data across functions
> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf > Of John C Nash > Sent: Thursday, April 05, 2012 1:20 PM > To: r-help at r-project.org > Subject: [R] Appropriate method for sharing data across functions > > In trying to streamline various optimization functions, I would like to have a scratch pad > of working data that is shared across a number of functions. These can be called from > different levels within some wrapper functions for maximum likelihood and other such > computations. I'm sure there are other applications that could benefit from this. > > Below are two approaches. One uses the <<- assignment to a structure I call OPCON. The > other attempts to create an environment with this name, but fails. Though I have looked > at > a number of references, I have so far not found an adequate description of how to > specify > where the OPCON environment is located. (Both the green and blue books do not cover > this > topic, at least not under "environment" in the index.) > > Is there a recommended approach to this? I realize I could use argument lists, but they > get long and tedious with the number of items I may need to pass, though passing the > OPCON > structure in and out might be the proper way.Make OPCON an environment and pass it into the functions that may read it or alter it. There is no real need to pass it out, since environments are changed in-place (unlike lists). E.g., > x <- list2env(list(one=1, two="ii", three=3)) > x <environment: 0x0000000003110890> > objects(x) [1] "one" "three" "two" > x[["two"]] [1] "ii" > with(x, three+one) [1] 4 > f <- function(z, env) { env[["newZ"]] <- z ; sqrt(z) } > f(10, x) [1] 3.162278 > x[["newZ"]] # put there by f() [1] 10 Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com> An onAttach() approach was suggested by > Paul > Gilbert and tried, but it has so far not succeeded and, unfortunately, does not seem to be > usable from source() i.e., cannot be interpreted but must be built first. > > JN > > Example using <<- > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > # npar is number of parameters ?? test?? > OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > # may be other stuff > ls(OPCON) > } > > add1<-function(){ > OPCON$KFN<<-1+OPCON$KFN > test<-OPCON$KFN > } > > OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > =====================> Example (failing) using new.env: > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > # npar is number of parameters ?? test?? > OPCON<-new.env(parent=globalenv()) > OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > # may be other stuff > ls(OPCON) > } > > add1<-function(){ > OPCON$KFN<-1+OPCON$KFN > test<-OPCON$KFN > } > > OPCON<-new.env(parent=globalenv()) > OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > ______________________________________________ > 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.
Hadley Wickham
2012-Apr-09 16:57 UTC
[R] Appropriate method for sharing data across functions
> Make OPCON an environment and pass it into the functions that may read it or alter it. ?There > is no real need to pass it out, since environments are changed in-place (unlike lists). ?E.g., > ?> x <- list2env(list(one=1, two="ii", three=3)) > ?> x > ?<environment: 0x0000000003110890> > ?> objects(x) > ?[1] "one" ? "three" "two" > ?> x[["two"]] > ?[1] "ii" > ?> with(x, three+one) > ?[1] 4 > ?> f <- function(z, env) { env[["newZ"]] <- z ; sqrt(z) } > ?> f(10, x) > ?[1] 3.162278 > ?> x[["newZ"]] # put there by f() > ?[1] 10The advantage of using a reference class is you get an object with defined behaviour, and something that you can document more easily. Hadley -- Assistant Professor / Dobelman Family Junior Chair Department of Statistics / Rice University http://had.co.nz/
Duncan Murdoch
2012-Apr-09 17:21 UTC
[R] Appropriate method for sharing data across functions
On 05/04/2012 4:20 PM, John C Nash wrote:> In trying to streamline various optimization functions, I would like to have a scratch pad > of working data that is shared across a number of functions. These can be called from > different levels within some wrapper functions for maximum likelihood and other such > computations. I'm sure there are other applications that could benefit from this. > > Below are two approaches. One uses the<<- assignment to a structure I call OPCON. The > other attempts to create an environment with this name, but fails. Though I have looked at > a number of references, I have so far not found an adequate description of how to specify > where the OPCON environment is located. (Both the green and blue books do not cover this > topic, at least not under "environment" in the index.) > > Is there a recommended approach to this?The one I would use is to create all of the functions that need access to the scratch pad as local functions within another. For example, makethem <- function() { MAXIMIZE <- TRUE PARSCALE <- rep(1, npar) KFN <- 0 ... etc ... add1 <- function(){ KFN <<- 1 + KFN } list(add1 = add1, ... other functions here...) } A single call to makethem() will return a list of functions which all have access to MAXIMIZE, PARSCALE, etc. If you like, you can pull them out of the list to be called independently, e.g. fns <- makethem() add1 <- fns$add1 and they'll still have access. (If this is a one-off need, you can use local( ) around the definitions, but I prefer the wrapper-function style.> I realize I could use argument lists, but they > get long and tedious with the number of items I may need to pass, though passing the OPCON > structure in and out might be the proper way. An onAttach() approach was suggested by Paul > Gilbert and tried, but it has so far not succeeded and, unfortunately, does not seem to be > usable from source() i.e., cannot be interpreted but must be built first. > > JN > > Example using<<- > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > # npar is number of parameters ?? test?? > OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > # may be other stuff > ls(OPCON) > }The code above creates OPCON as a global variable; that's dangerous, if you have multiple different optimizers potentially being used.> > add1<-function(){ > OPCON$KFN<<-1+OPCON$KFN > test<-OPCON$KFN > } > > OPCON<<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > =====================> Example (failing) using new.env: > > rm(list=ls()) > optstart<-function(npar){ # create structure for optimization computations > # npar is number of parameters ?? test?? > OPCON<-new.env(parent=globalenv()) > OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,npar), FNSCALE=1, > KFN=0, KGR=0, KHESS=0)This failed because the second assignment wiped out the first: you created a new environment, then threw it away when you assigned a list to OPCON. The other problem with this approach is that you never saved OPCON anywhere, so when optstart() was done, it would disappear. Hadley suggested using a reference class, and Bill suggested using an environment explicitly; those are both possible alternatives. My version creates an environment but never names it; it's the environment of the add1() function and other functions defined within makethem(). I'd say the more formal versions they suggested would be better if you had a longer (or open-ended) list of possible functions you wanted to work with, or if you wanted to pass your OPCON to the user to manipulate. Duncan Murdoch> # may be other stuff > ls(OPCON) > } > > add1<-function(){ > OPCON$KFN<-1+OPCON$KFN > test<-OPCON$KFN > } > > OPCON<-new.env(parent=globalenv()) > OPCON<-list(MAXIMIZE=TRUE, PARSCALE=rep(1,4), FNSCALE=1, > KFN=0, KGR=0, KHESS=0) > ls(OPCON) > print(add1()) > print(add1()) > print(ls.str()) > > rm(OPCON) # Try to remove the scratchpad > print(ls()) > > tmp<-readline("Now try from within a function") > setup<-optstart(4) # Need to sort out how to set this up appropriately > cat("setup =") > print(setup) > > print(add1()) > print(add1()) > > rm(OPCON) # Try to remove the scratchpad > > ______________________________________________ > 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.