запуск функции внутри функции и объект не найден

#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