R usa o escopo lexical, o que significa que, se um objeto é referenciado, mas não definido em uma função, ele é procurado no ambiente em que a função está definida , não no ambiente do qual foi chamado.
z é referenciado em g, mas não é definido em g; portanto, ele olha para o ambiente em que g está definido e esse é o ambiente em f; portanto, g usa z = 4.
Na verdade, nesse caso, o ambiente em que g é definido é o mesmo que o ambiente em que g é chamado; portanto, de qualquer maneira que você o veja, z = 4 deve ser usado. Se as funções padronizadas no ambiente global para procurar objetos não definidos na função, ele usaria z = 10, mas não é assim que R funciona.
Fazendo funcionar de maneira diferente
Se, por algum motivo, você quiser forçar g a procurar z no ambiente em que f é chamado, você poderá fazer isso (onde parent.frame()
se refere ao ambiente a partir do qual f é chamado).
f2 <- function(x, envir = parent.frame()) {
g <- function(y) {
y + with(envir, z)
}
z <- 4
x + g(x)
}
z <- 10
f2(3)
## [1] 16
ou poderíamos usar, y + envir$z
exceto que isso pareceria apenas no quadro pai e não em seus ancestrais, ao passo with
que procurará nos ancestrais do quadro pai, se não encontrado no quadro pai.
Uma alternativa é alterar o ambiente de g dessa maneira, para procurar envir
objetos não encontrados em 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