Home > Software design >  running a function within a function and object not being found
running a function within a function and object not being found

Time:11-20

I am embarrassed that I'm asking this question, and I wonder if it has something fundamental to do with scoping that I'm not understanding.

i have two functions, beta and alpha

beta <- function(b) {
  foo <- b   x
  print(foo)
}

and

alpha <- function(a) {
  x <- a   5
  print(x)
  beta(2)
}

When I run alpha(1) I'm expecting the output of beta to be 8. However, I get an error message about object 'x' not being found.

Question: shouldn't beta know that x is 6? I think I am missing something obvious.

CodePudding user response:

R uses lexical scoping. That means that values are first looked up in the function itself and then in the environment where the function was defined.

When you define both alpha and beta in the global environment, beta looks up x in the global environment.

beta <- function(b) {
  foo <- b   x
  print(foo)
}

alpha <- function(a) {
  x <- a   5
  print(x)
  beta(2)
}

alpha(1)
#> [1] 6
#> Error in beta(2): object 'x' not found

Created on 2021-11-19 by the reprex package (v1.0.0)

In contrast, if you define beta within alpha, x is found (because x is also defined in the environment where beta is defined):

alpha <- function(a) {
  x <- a   5
  print(x)
  
  beta <- function(b) {
    foo <- b   x
    print(foo)
  }
  beta(2)
}

alpha(1)
#> [1] 6
#> [1] 8

Created on 2021-11-19 by the reprex package (v1.0.0)

CodePudding user response:

The problem is that both alpha and beta are declared inside the Global Environment.

Every function looks for unknown objects into the parent environment. beta's parent environment is the global environment, so when x is called beta will look for x in the Global Environment: it can't "see" what was created inside alpha's environment.

It would work as you expect:

  • if you declare beta inside alpha environment:
alpha <- function(a) {
  beta <- function(b) {
    foo <- b   x
    print(foo)
  }
  x <- a   5
  print(x)
  beta(2)
}
alpha(1)
#> [1] 6
#> [1] 8
  • or if you tell beta in which environment it should look for x:
beta <- function(b, env = parent.frame()) {
  
  x <- get("x", envir = env)
  foo <- b   x
  print(foo)

}

alpha <- function(a) {
  
  x <- a   5
  print(x)
  beta(2) # by default beta takes alpha's environment as parent frame!

}

alpha(1)
#> [1] 6
#> [1] 8

There are also other options, like assigning x to the alpha's parent environment, but I wouldn't do that.

beta <- function(b) {
  
  foo <- b   x
  print(foo)
  
}

alpha <- function(a) {
  
  x <<- a   5
  print(x)
  beta(2)
  
}

alpha(1)
#> [1] 6
#> [1] 8

I would suggest you to have a look at this.

CodePudding user response:

What about specifying x in beta()?

beta <- function(b, x) {
  foo <- b   x
  print(foo)
}


alpha <- function(a) {
  x <- a   5
  print(x)
  beta(2, x)
}

alpha(1)
# [1] 6
# [1] 8
  •  Tags:  
  • r
  • Related