Matthieu Stigler
2010-Nov-15 12:48 UTC
[R] How to move an internal function to external keeping same environment?
Hi I have within a quite big function foo1, an internal function foo2. Now, in order to have a cleaner code, I wish to have the internal foo2 as "external". This foo2 was using arguments within the foo1 environment that were not declared as inputs of foo2, which works as long as foo2 is within foo1, but not anymore if foo2 is external, as is the case now. Now, I could add all those arguments as inputs to foo2, but I feel if foo2 is called often, I would be copying those objects more than required. Am I wrong? I then used this to avoid to declare explcitely each argument to foo2: foo1<-function(x){ b<-x[1]+2 environment(foo2)<-new.env(parent =as.environment(-1)) c<-foo2(x) return(c) } foo2<-function(x) x*b #try: foo1(1:100) This works. But I wanted to be sure: -am I right that if I instead declare each element to be passed to foo2, this would be more copying than required? (imagine b in my case a heavy dataset, foo2 a long computation) -is this lines "environment(foo2)<-new.env(parent =as.environment(-1))" the good way to do it or it can have unwanted implications? Thanks a lot!! Matthieu
Gabor Grothendieck
2010-Nov-15 13:05 UTC
[R] How to move an internal function to external keeping same environment?
On Mon, Nov 15, 2010 at 7:48 AM, Matthieu Stigler <matthieu.stigler at gmail.com> wrote:> Hi > > I have within a quite big function foo1, an internal function foo2. Now, in > order to have a cleaner code, I wish to have the internal foo2 as > "external". This foo2 was using arguments within the foo1 environment that > were not declared as inputs of foo2, which works as long as foo2 is within > foo1, but not anymore if foo2 is external, as is the case now. > > Now, I could add all those arguments as inputs to foo2, but I feel if foo2 > is called often, I would be copying those objects more than required. Am I > wrong? > > I then used this to avoid to declare explcitely each argument to foo2: > > foo1<-function(x){ > ?b<-x[1]+2 > ?environment(foo2)<-new.env(parent =as.environment(-1)) > ?c<-foo2(x) > > return(c) > } > > foo2<-function(x) ?x*b > #try: > foo1(1:100) > > > This works. But I wanted to be sure: > > -am I right that if I instead declare each element to be passed to foo2, > this would be more copying than required? (imagine b in my case a heavy > dataset, foo2 a long computation) > -is this lines "environment(foo2)<-new.env(parent =as.environment(-1))" the > good way to do it or it can have unwanted implications? >This would be good enough (replacing your environment(foo2)<-... line): environment(foo2) <- environment() If you add parameters to foo2 it won't actually copy them unless they are modified in foo2. -- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com
Duncan Murdoch
2010-Nov-15 13:14 UTC
[R] How to move an internal function to external keeping same environment?
On 15/11/2010 7:48 AM, Matthieu Stigler wrote:> Hi > > I have within a quite big function foo1, an internal function foo2. Now, > in order to have a cleaner code, I wish to have the internal foo2 as > "external". This foo2 was using arguments within the foo1 environment > that were not declared as inputs of foo2, which works as long as foo2 is > within foo1, but not anymore if foo2 is external, as is the case now. > > Now, I could add all those arguments as inputs to foo2, but I feel if > foo2 is called often, I would be copying those objects more than > required. Am I wrong? > > I then used this to avoid to declare explcitely each argument to foo2: > > foo1<-function(x){ > b<-x[1]+2 > environment(foo2)<-new.env(parent =as.environment(-1)) > c<-foo2(x) > > return(c) > } > > foo2<-function(x) x*b > #try: > foo1(1:100) > > > This works. But I wanted to be sure: > > -am I right that if I instead declare each element to be passed to foo2, > this would be more copying than required? (imagine b in my case a heavy > dataset, foo2 a long computation) > -is this lines "environment(foo2)<-new.env(parent =as.environment(-1))" > the good way to do it or it can have unwanted implications?I don't think modifying the environment of a closure could be seen as a way to get cleaner code. I'd just leave foo2 within foo1. There are several unwanted implications of the way you do it: - Setting the environment of foo2 to the foo1 evaluation frame means those local variables won't be garbage collected. If foo1 creates a large temporary matrix, it will take up space in memory until you modify foo2 again. - If we say that foo2 has global scope (it might be limited to your package namespace, but let's call that global), then your foo1 has global side effects, and those are often a bad idea. For example, suppose next week you define foo3 that also uses and modifies foo2. It's very easy for foo1 and foo3 to clash with conflicting use of the global foo2. Don't use globals unless you really have to. Duncan Murdoch