0Pricing
R Academy · Aula

Regras de escopo léxico

Entenda como R encontra variáveis pesquisando ambientes-pai.

Regras de escopo léxico é uma aula grátis de R Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.

O que é escopo léxico

Escopo léxico significa que uma função procura variáveis onde foi definida, não onde é chamada. O R usa escopo léxico. Isso é previsível: o ambiente pesquisado por uma função é fixado no momento de sua criação, não no momento da chamada.

x <- 'global'
f <- function() {
  cat('x =', x, '\n')  # looks where f was defined (global)
}
local({
  x <- 'local to local block'
  f()  # still prints global x, not the local one
})

Escopo léxico versus dinâmico

No escopo dinâmico (usado em algumas outras linguagens), uma função encontraria a variável no ambiente de chamada. O R usa escopo léxico: o ambiente envolvente no momento da definição sempre prevalece. Isso faz com que as funções se comportem de maneira consistente, independentemente de onde sejam chamadas.

val <- 100
make_adder <- function(n) {
  # n is captured from the definition environment
  function(x) x + n
}
add10 <- make_adder(10)
add20 <- make_adder(20)
cat(add10(5), '\n')   # 15 — n=10 from definition
cat(add20(5), '\n')   # 25 — n=20 from definition

Variáveis livres e fechamentos

Uma variável dentro de uma função que não é um parâmetro nem uma atribuição local é uma variável livre. O R a procura no ambiente envolvente. Uma função que captura variáveis livres é chamada de fechamento.

base_rate <- 0.05   # free variable captured by f
f <- function(principal, years) {
  principal * (1 + base_rate) ^ years
}
cat('5 yr return:', f(1000, 5), '\n')
# Even if we change base_rate later:
base_rate <- 0.08
cat('New rate return:', f(1000, 5), '\n')

Fechamentos capturam ambientes

Cada vez que uma função fábrica é chamada, a função retornada (fechamento) captura uma imagem do ambiente envolvente. Chamadas diferentes produzem fechamentos com valores capturados diferentes — essa é a base das fábricas de funções.

power_fn <- function(exp) {
  function(x) x ^ exp
}
square <- power_fn(2)
cube   <- power_fn(3)
cat('square(4) =', square(4), '\n')
cat('cube(3)   =', cube(3),   '\n')

O operador <<-

<<- (atribuição com seta dupla) procura na cadeia de pais um vínculo existente e o modifica no próprio lugar. Se nenhum vínculo for encontrado, ele cria um no ambiente global. Essa é a ferramenta para modificar uma variável em um escopo envolvente a partir de dentro de uma função.

count <- 0
increment <- function() {
  count <<- count + 1
}
increment()
increment()
increment()
cat('count:', count, '\n')

<<- com fechamentos

O uso mais idiomático de <<- é dentro de fechamentos que precisam atualizar o estado em seu ambiente envolvente. Isso cria funções com estado — funções com memória persistente entre chamadas.

make_counter <- function() {
  n <- 0
  list(
    increment = function() n <<- n + 1,
    get       = function() n,
    reset     = function() n <<- 0
  )
}
ctr <- make_counter()
ctr$increment()
ctr$increment()
cat('Count:', ctr$get(), '\n')
ctr$reset()
cat('After reset:', ctr$get(), '\n')

Escopo em funções aninhadas

Quando as funções são aninhadas, a função interna pode acessar variáveis definidas na função externa. O ambiente da função externa se torna o ambiente envolvente da função interna, formando uma cadeia.

outer <- function() {
  greeting <- 'Hello'
  inner <- function(name) {
    # greeting comes from outer's environment
    paste(greeting, name)
  }
  inner('World')
}
cat(outer(), '\n')

Pesquisando a cadeia de escopos

Quando o R procura uma variável, ele pesquisa os ambientes nesta ordem: próprio da função → envolvente → envolvente do envolvente → ... → global → caminho de pesquisa → base → vazio. A primeira correspondência prevalece.

x <- 'global'
f <- function() {
  x <- 'local to f'
  g <- function() {
    # g has no x, so looks in f's env
    cat('g sees x =', x, '\n')
  }
  g()
}
f()

environment() de uma função

Você pode inspecionar o ambiente envolvente de qualquer função com environment(f). Também pode defini-lo com environment(f) <- e, alterando onde a função procurará variáveis livres — uma técnica poderosa, porém avançada.

x <- 'global_x'
f <- function() x
cat('f sees:', f(), '\n')

# Change f's enclosing environment
my_env <- new.env(parent = emptyenv())
my_env$x <- 'env_x'
environment(f) <- my_env
cat('f now sees:', f(), '\n')

Fechamento prático: memoização

O escopo léxico + <<- permite fazer memoização: armazene resultados dispendiosos da função no ambiente do fechamento. O cache é privado ao fechamento e persiste entre chamadas.

make_memoized_fib <- function() {
  cache <- c()
  function(n) {
    if (!is.null(cache[n])) return(cache[n])
    if (n <= 1) { cache[n] <<- n; return(n) }
    result <- Recall(n-1) + Recall(n-2)
    cache[n] <<- result
    result
  }
}
fib <- make_memoized_fib()
cat(sapply(0:8, fib), '\n')

Armadilha do escopo léxico: variáveis de laço

Uma armadilha clássica é criar fechamentos dentro de um laço. Todos os fechamentos capturam o mesmo ambiente, não uma imagem do valor. Quando forem chamados, a variável do laço já terá seu valor final.

fns <- vector('list', 3)
for (i in 1:3) {
  local({
    captured_i <- i
    fns[[captured_i]] <<- function() captured_i
  })
}
cat(fns[[1]](), fns[[2]](), fns[[3]](), '\n')

Verificação rápida

Com o escopo léxico do R, onde uma função procura uma variável livre (que não foi definida na própria função)?

Escopo léxico: principais conclusões

Principais conclusões sobre escopo léxico:

  • O R usa escopo léxico — as funções procuram variáveis onde foram definidas
  • Uma função captura seu ambiente envolvente como um fechamento
  • As variáveis livres são resolvidas no momento da definição, não da chamada
  • <<- modifica um vínculo na cadeia de pais (ou no ambiente global, se não for encontrado)
  • Fechamentos + <<- = funções com estado privado persistente
  • Armadilha de fechamentos em laços: use local() para forçar um novo ambiente a cada iteração
make_multiplier <- function(factor) {
  function(x) x * factor
}
double <- make_multiplier(2)
triple <- make_multiplier(3)
cat('double(7):', double(7), '\n')
cat('triple(7):', triple(7), '\n')
cat('double env factor:', get('factor', envir = environment(double)), '\n')

Perguntas Frequentes

A aula “Regras de escopo léxico” é grátis?

Sim — o texto completo de “Regras de escopo léxico” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.

O que vou aprender em “Regras de escopo léxico”?

Entenda como R encontra variáveis pesquisando ambientes-pai. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar R Academy?

Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Regras de escopo léxico”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de R Academy?

Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. O que é um ambiente em R?
  2. Regras de escopo léxico
  3. Escopo global versus local
  4. Criando e inspecionando ambientes
← Voltar para R Academy