1

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.

3 Answers 3

2

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)

Sign up to request clarification or add additional context in comments.

Comments

2

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.

1 Comment

Thank you! I'm embarrassed that I've been using R for all these years but didn't know these principals.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.