#r
Вопрос:
Мне неловко, что я задаю этот вопрос, и мне интересно, имеет ли он какое-то фундаментальное отношение к области охвата, которую я не понимаю.
у меня есть две функции, beta
и alpha
beta <- function(b) {
foo <- b x
print(foo)
}
и
alpha <- function(a) {
x <- a 5
print(x)
beta(2)
}
Когда я запускаю alpha(1)
, я ожидаю, что результат beta
будет равен 8. Однако я получаю сообщение об ошибке о том, что объект «x» не найден.
Вопрос: не следует ли beta
знать, что x равно 6? Я думаю, что упускаю что-то очевидное.
Ответ №1:
R
использует лексический охват. Это означает, что значения сначала ищутся в самой функции, а затем в среде, в которой была определена функция.
Когда вы определяете и alpha
то, и beta
другое в глобальной среде, beta
посмотрите x
в глобальной среде.
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
Создано в 2021-11-19 годах пакетом reprex (v1.0.0)
Напротив, если вы определяете beta
внутри alpha
, x
находится (потому x
что также определяется в среде, в которой beta
определяется):
alpha <- function(a) {
x <- a 5
print(x)
beta <- function(b) {
foo <- b x
print(foo)
}
beta(2)
}
alpha(1)
#> [1] 6
#> [1] 8
Создано в 2021-11-19 годах пакетом reprex (v1.0.0)
Ответ №2:
Проблема в том, что и alpha
то, и beta
другое декларируется внутри Глобальной среды.
Каждая функция ищет неизвестные объекты в родительской среде. beta
родительская среда-это глобальная среда, поэтому, когда x
вызывается beta
, будет искать x
в глобальной среде: она не может «видеть» то, что было создано внутри alpha
среды.
Это будет работать так, как вы ожидаете:
- если вы объявите
beta
внутреннююalpha
среду:
alpha <- function(a) {
beta <- function(b) {
foo <- b x
print(foo)
}
x <- a 5
print(x)
beta(2)
}
alpha(1)
#> [1] 6
#> [1] 8
- или если вы скажете
beta
, в какой среде он должен искать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
Есть и другие варианты, например, назначение x
родительской среде альфа-сервера, но я бы этого не делал.
beta <- function(b) {
foo <- b x
print(foo)
}
alpha <- function(a) {
x <<- a 5
print(x)
beta(2)
}
alpha(1)
#> [1] 6
#> [1] 8
Я бы посоветовал вам взглянуть на это.
Комментарии:
1. Спасибо! Мне стыдно, что я использовал R все эти годы, но не знал этих принципов.
Ответ №3:
Как насчет указания x
в 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