1

Suppose I have these two functions:

fInner<-function()
{
   # Do some complicated stuff, and...
    I<<-I+1
}

fOuter<-function()
{
    I<-0
    fInner()
    print(I)
}

Calling fOuter() produces an error: Error in fInner() : object 'I' not found. I know, that one way of fixing it is to re-write the example into

fOuter<-function()
{
    fInner<-function()
    {
        I<<-I+1
    }
    I<-0
    fInner()
    print(I)
}

But what if I don't want to nest the functions that way? In my case fInner is a very heavy and complicated function (which I might want to move into my library), and fOuter is really an ad-hoc created function that defines one iterator. I will have many fOuter-class functions in my code, so nesting them will require duplicating the fInner inside every single little one iterator definition.

I suspect the solution has something to do with environments, but I don't know how to do it. Can anyone help?

Adam Ryczkowski
  • 7,592
  • 13
  • 42
  • 68
  • 4
    For some reason I doubt you're going to heed this advice, but it's really probably better to just have `fInner` return the new value of `I`, and then it's available for assignment if needed. – joran Aug 10 '13 at 17:59
  • @joran :-D Well, actually that's a very good answer. I don't know why it didn't come to me at the beginning. But, out of curiosity (not any longer necessity) the question stands. – Adam Ryczkowski Aug 10 '13 at 18:03

1 Answers1

3

You need access to the environment associated with the fOuter function--where the call to fInner is. You can get this with parent.frame, and you can get and set variables with get and assign:

fInner<-function()
{
  assign("I", get("I", envir=parent.frame()) + 1, envir=parent.frame())
}

fOuter<-function()
{
  I<-0
  fInner()
  print(I)
}

See ?environment and ?parent.frame for more info.

But this is just to satisfy your curiosity! You seem to agree that this is not a good idea. Manipulating environments and names can quickly get complicated, and unless you're doing something truly complex, there's probably a better way.

Peyton
  • 7,266
  • 2
  • 29
  • 29