Re: [Rd] Return function from function with minimal environment

From: Gabor Grothendieck <ggrothendieck_at_gmail.com>
Date: Tue 04 Apr 2006 - 15:10:49 GMT

On 4/4/06, Henrik Bengtsson <hb@maths.lth.se> wrote:
> On 4/4/06, Thomas Lumley <tlumley@u.washington.edu> wrote:
> > 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 "{".

>

> Thank you, this makes sense. Modifying Roger Peng's example
> illustrates what you say:
>

> foo <- function(huge) {
> scale <- mean(huge)
> g <- function(x) x
> environment(g) <- emptyenv()
> g
> }
>

> fcn <- foo(1:10e5)
> fcn(2)
> # [1] 2
>

> But as soon as you add "something" to the g(), it is missing;
>

> foo <- function(huge) {
> scale <- mean(huge)
> g <- function(x) { x }
> environment(g) <- emptyenv()
> g
> }
>

> fcn <- foo(1:10e5)
> fcn(2)
> # Error in fcn(2) : attempt to apply non-function
>

> ...and I did not know that "{" and "(" are primitive functions. Interesting.
>

> I conclude that 'env <- new.env(parent=baseenv())' is better than
> ''env <- new.env()' in my case.

Is there any reason to use

   env <- new.env(parent=baseenv())

instead of just

   env <- baseenv() ?

The extra environment being created seems to serve no purpose.



R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Wed Apr 05 01:35:02 2006

This archive was generated by hypermail 2.1.8 : Tue 04 Apr 2006 - 18:16:47 GMT