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

From: Martin Maechler <maechler_at_stat.math.ethz.ch>
Date: Tue 04 Apr 2006 - 15:11:24 GMT

>>>>> "Roger" == Roger D Peng <rpeng@jhsph.edu> >>>>> on Tue, 04 Apr 2006 10:38:29 -0400 writes:

    Roger> In R 2.3.0-to-be, I think you can do

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

yes, but for now, and for the given purpose, also as seen in examples, such as splinefun() or approxfun(), just rm() the things you don't want in the environment. I.e.,

 foo <- function(huge) {

    scale <- mean(huge)
    rm(huge)
    function(x) { scale * x }
 }

Martin

    Roger> -roger

    Roger> 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
>>
>> 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
>>
>> ______________________________________________
>> R-devel@r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>

    Roger> --
    Roger> Roger D. Peng | http://www.biostat.jhsph.edu/~rpeng/

    Roger> ______________________________________________
    Roger> R-devel@r-project.org mailing list     Roger> https://stat.ethz.ch/mailman/listinfo/r-devel

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 - 16:17:00 GMT