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
insidealpha
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 forx
:
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