[R] Appropriate method for sharing data across functions
Duncan Murdoch
murdoch.duncan at gmail.com
Mon Apr 9 19:21:00 CEST 2012
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.
More information about the R-help
mailing list