Escopo
Como os nomes são resolvidos, e o que shadow faz.
A cadeia de escopos#
Cada bloco cria um escopo filho. Ao procurar um nome, o interpretador sobe a cadeia até encontrá-lo — ou dispara NameError_.
global := "topo"
action externa():
da_acao := "acao"
action interna():
do_bloco := "interna"
out global, da_acao, do_bloco # enxerga os três
interna()
externa()Atribuir atualiza onde existe#
contador := 0
action incrementar():
contador := contador + 1 # atualiza o de FORA
yield contador
incrementar()
incrementar()
out contador # 2:= procura o nome na cadeia. Se encontra, atualiza ali. Se não encontra, cria no escopo atual.
shadow — uma cópia local#
x := 10
action sombreia():
shadow x := 99 # cria uma cópia local, não toca no de fora
yield x
out sombreia(), x # 99 10shadow diz explicitamente "este nome é meu, aqui dentro". Sem ele, a atribuição afetaria o x externo.
Escopos de bloco#
Laços, condicionais e blocos monitor criam escopos próprios. A variável do cycle existe só ali dentro:
cycle i from 1 to 3:
dentro := i * 2
# out i # erro — 'i' não existe aqui foraO mesmo vale para a variável de uma compreensão.
Closures#
Uma ação aninhada captura o escopo onde foi criada, e o mantém vivo mesmo depois que a ação externa terminou:
action fabrica(n):
action somador(x):
yield x + n # 'n' continua acessível
yield somador
soma5 := fabrica(5)
out soma5(10) # 15 — 'n' ainda vale 5Detalhes em Closures e lambdas.
self e this#
Dentro de um método, self (ou this, sinônimo) é a instância atual:
blueprint Conta(saldo):
action depositar(valor):
self.saldo := self.saldo + valor
yield self.saldoConstantes#
steady marca o nome como imutável naquele escopo. Reatribuir dispara erro, mesmo de dentro de uma ação aninhada.
Módulos#
Cada arquivo importado tem seu próprio escopo de topo, e só exporta o que o relay permitir. Veja Módulos.