R использует лексическую область видимости, что означает, что если объект ссылается, но не определен в функции, то он ищется в среде, в которой функция определена , а не в среде, из которой он был вызван .
z упоминается в g, но не определен в g, поэтому он смотрит на среду, в которой определено g, и это среда в f, поэтому g использует z = 4.
На самом деле в этом случае среда, в которой определяется g, такая же, как среда, из которой вызывается g, поэтому при любом взгляде на нее следует использовать z = 4. Если функции по умолчанию обращаются к глобальной среде для поиска объектов, не определенных в функции, то она будет использовать z = 10, но это не то, как работает R.
Как заставить его работать по-другому
Если по какой-то причине вы хотите заставить g искать z в среде, в которой вызывается f, то вы можете сделать это (где parent.frame()
относится к окружение, из которого вызывается f).
f2 <- function(x, envir = parent.frame()) {
g <- function(y) {
y + with(envir, z)
}
z <- 4
x + g(x)
}
z <- 10
f2(3)
## [1] 16
или мы можем использовать y + envir$z
за исключением того, что он будет выглядеть только в родительском фрейме, а не в его предках, тогда как with
будет искать в предках родителя кадр, если он не найден в родительском кадре.
Альтернатива состоит в том, чтобы изменить окружение g таким образом, чтобы он смотрел в envir
объекты, не найденные в g:
f3 <- function(x, envir = parent.frame()) {
g <- function(y) {
y + z
}
environment(g) <- envir
z <- 4
x + g(x)
}
z <- 10
f3(3)
## [1] 16