[Rd] Return function from function with minimal environment
Thomas Lumley
tlumley at u.washington.edu
Tue Apr 4 16:29:59 CEST 2006
On Tue, 4 Apr 2006, Henrik Bengtsson wrote:
> Hi,
>
> this relates to the question "How to set a former environment?" asked
> yesterday. What is the best way to to return a function with a
> minimal environment from a function? Here is a dummy example:
>
> foo <- function(huge) {
> scale <- mean(huge)
> function(x) { scale * x }
> }
>
> fcn <- foo(1:10e5)
>
> The problem with this approach is that the environment of 'fcn' does
> not only hold 'scale' but also the memory consuming object 'huge',
> i.e.
>
> env <- environment(fcn)
> ll(envir=env) # ll() from R.oo
> # member data.class dimension object.size
> # 1 huge numeric 1000000 4000028
> # 2 scale numeric 1 36
>
> save(env, file="temp.RData")
> file.info("temp.RData")$size
> # [1] 2007624
>
> I generate quite a few of these and my 'huge' objects are of order
> 100Mb, and I want to keep memory usage as well as file sizes to a
> minimum. What I do now, is to remove variable from the local
> environment of 'foo' before returning, i.e.
>
> foo2 <- function(huge) {
> scale <- mean(huge)
> rm(huge)
> function(x) { scale * x }
> }
>
> fcn <- foo2(1:10e5)
> env <- environment(fcn)
> ll(envir=env)
> # member data.class dimension object.size
> # 1 scale numeric 1 36
>
> save(env, file="temp.RData")
> file.info("temp.RData")$size
> # [1] 156
>
> Since my "foo" functions are complicated and contains many local
> variables, it becomes tedious to identify and remove all of them, so
> instead I try:
>
> foo3 <- function(huge) {
> scale <- mean(huge);
> env <- new.env();
> assign("scale", scale, envir=env);
> bar <- function(x) { scale * x };
> environment(bar) <- env;
> bar;
> }
>
> fcn <- foo3(1:10e5)
>
> But,
>
> env <- environment(fcn)
> save(env, file="temp.RData");
> file.info("temp.RData")$size
> # [1] 2007720
>
> When I try to set the parent environment of 'env' to emptyenv(), it
> does not work, e.g.
>
> fcn(2)
> # Error in fcn(2) : attempt to apply non-function
>
> but with the new.env(parent=baseenv()) it works fine. The "base"
> environment has the empty environment as a parent. So, I try to do
> the same myself, i.e. new.env(parent=new.env(parent=emptyenv())), but
> once again I get
I don't think you want to remove baseenv() from the environment. If you
do, no functions from baseenv will be visible inside fcn. These include
"{" and "*", which are necessary for your function. I think the error
message comes from being unable to find "{".
Also, there is no memory use from having baseenv in the environment, since
all the objects in baseenv are always present.
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle
More information about the R-devel
mailing list