Re: [R] Appropriate method for sharing data across functions
Thanks to Hadley, William and Duncan for suggestions. I'm currently implementing a solution that is close to that of William and Duncan (and learning more about environments in the process). I suspect the reference classes are possibly a more reliable long term solution. I'll plead laziness until I find the other approach won't work. For anyone interested in these issues, over the next few weeks the outcome of my investigations and trials should be on the SVN repository of R-forge under Optimization and Solving Tools, https://r-forge.r-project.org/R/?group_id=395, in particular within the packages optfntools and optimx. However, it will be late April before things stabilize. John Nash __ R-help@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.
Re: [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@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. __ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEAS
Re: [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 > > > 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 The 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/ __ R-help@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.
Re: [R] Appropriate method for sharing data across functions
> -Original Message- > From: r-help-boun...@r-project.org [mailto:r-help-boun...@r-project.org] On > Behalf > Of John C Nash > Sent: Thursday, April 05, 2012 1:20 PM > To: r-help@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 > 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@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. __ R-help@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.
Re: [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 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@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/ __ R-help@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.
[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 __ R-help@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.