0

I read about scoping in 'Advanced R' and still didn't figure this out.

I defined two functions.

in file 'f1.R':

f1 = function(x, y) {

        x = x + 1
        y = y + 1
        z = 1

        fsum(x, y)        
}

in file 'fsum.R':

fsum = function(x, y){

        x + y + z
}

Now it doesn't work because fsum can't find z, due to scope issue

> source('f1.R')
> source('fsum.R')
> f1(1,1)
Error in fsum(x, y) : object 'z' not found
> environment(f1)
<environment: R_GlobalEnv>
> environment(fsum)
<environment: R_GlobalEnv>

How can I make fsum to look up for needed variables in local environment? I did some test, and


Solution 1: explicitly pass the variable as argument in file 'f1.R':

f1 = function(x, y) {

        x = x + 1
        y = y + 1
        z = 1

        fsum(x, y, z)        
}

in file 'fsum.R':

fsum = function(x, y, z){

        x + y + z
}

Now it works:

> source('f1.R')
> source('fsum.R')
> f1(1,1)
[1] 5

But what if there are lots of variables needed in fsum and I don't want to explicitly write them down? Thanks for help. Any recommendation of readings is appreciated.

PS: I read something about making variables global using <<. This is not what I'm looking for. I'd like variables to be local.


Solution 2: If a function is defined in another function, then its environment is the local, and it can access the variables.

In this case I don't want to define fsum inside f1 anyway because I want to use fsum anywhere)

in file 'f1.R':

f1 = function(x, y) {

        x = x + 1
        y = y + 1
        z = 1

        source('fsum.R', local=T)

        fsum(x, y)      
}

in file 'fsum.R':

fsum = function(x, y){

        x + y + z
}

And it works:

> source('f1.R')
> f1(1,1)
[1] 5
YJZ
  • 3,934
  • 11
  • 43
  • 67
  • 1
    The crucial element here is where the function is created. If you put the definition of `fsum` inside of the definition of `f1` it works. – joran Sep 18 '15 at 21:34
  • 2
    In general I'd advise against doing this sort of thing. Sooner or later a naming conflict and/or a forgotten external variable will lead to trouble. – Carl Witthoft Sep 18 '15 at 21:41
  • @CarlWitthoft Indeed, I was trying to withhold my urge to say this just seems like a terrible idea. It's not too far from succumbing to the temptation to define `fsum` inside `f1` using `<<-` so it's accessible in the global environment, and then the results of calling `fsum` become really difficult to predict. – joran Sep 18 '15 at 21:43
  • Hi thanks for the suggestions about style. I agree explicitly writing all variables is good and safe. Could you recommend something (book/chapters) to read about this? – YJZ Sep 18 '15 at 22:06
  • Hi @joran I read about defining a function inside another. But some test seems not work, see update OP please. – YJZ Sep 18 '15 at 22:08
  • Try `source('fsum.R',local = TRUE)` (and of course read the associated documentation at `?source`). But your "put each function in a file" style feels very Matlab-y to me, and some of the style feedback you're getting is partly aimed to steer you away from writing code in R using a coding style from a very different language. – joran Sep 18 '15 at 22:17
  • Hi @joran - thanks a lot. Now it works and I updated OP – YJZ Sep 18 '15 at 22:25
  • Hi @joran - thanks a lot for your help. I do appreciate the feedback on styling. Yes I use Matlab a lot, but didn't have training in Matlab styling in either... Hey could you recommend me something to read? thanks a lot – YJZ Sep 18 '15 at 22:28

1 Answers1

0

I guess that this SO answer nicely describes what happen when you try to get z variable in fsum.R.

According to that answer, solution for your case is:

f1 <- function(x, y) {

  x <- x + 1
  y <- y + 1
  z <- 1

  environment(fsum) <- environment() # This line points fsum environment to current one
  fsum(x, y)
}
Community
  • 1
  • 1