[Rd] Return function from function with minimal environment

Henrik Bengtsson hb at maths.lth.se
Tue Apr 4 15:40:36 CEST 2006


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

fcn(2)
# Error in fcn(2) : attempt to apply non-function

Apparently, I do not understand enough here.  Please, enlighten me. In
the meantime I stick with foo2().

Best,

Henrik



More information about the R-devel mailing list