Scope

Um escopo é semelhante a um dicionário, onde valores estão associados a chaves.

Definição

Escopos são definidos usando chaves {}, conforme mostrado abaixo:

meuEscopoBacana = {
  lugar = 'aqui'
  quando = 'agora'
}

Escopos armazenam entradas em ordem alfabética, uma característica que se torna aparente ao mapear sobre um escopo.

Acesso

Há três maneiras de acessar diretamente as entradas dentro de um escopo.

Sintaxe de ponto

meuEscopoBacana.lugar  # retorna: 'aqui'

Sintaxe de obtenção

# assumindo que prop = 'lugar'
meuEscopoBacana(prop)  # retorna: 'aqui'

Em ambos os métodos, se a propriedade não estiver presente, null é retornado. Se o escopo externo não for encontrado, um erro é gerado.

Sintaxe de encadeamento opcional

Use o operador interrogação-ponto ?. para encadear com segurança escopos externos potencialmente inexistentes:

naoExistente?.prop  # retorna null

A sintaxe de encadeamento opcional não gera um erro quando o escopo externo é null.

Operações

  • == igual
  • != diferente
  • + adição (efeito de mesclagem)
  • - subtração (efeito de diferença)
  • & AND lógico
  • | OR lógico

AND/OR lógico avaliam escopos vazios como false, caso contrário, true

Adição de escopo (mesclagem)

O segundo operando age como um patch para o primeiro:

x = { a = 1, b = 3 }
y = { b = 2 }

x + y  # resulta em { a = 1, b = 2 }
y + x  # resulta em { a = 1, b = 3 }

valores do segundo operando substituem os do primeiro

Subtração de escopo (diferença)

A subtração remove elementos do primeiro operando que são idênticos aos do segundo:

x = { a = 1, b = 3 }
y = { a = 1 }

x - y  # resulta em { b = 3 }

apenas valores exatamente idênticos são removidos

Blocos Escopados

Blocos Escopados em FatScript permitem a execução de declarações dentro do contexto de um escopo específico:

objeto.{
  # Declarações executadas no contexto de 'objeto'
}

Aqui, objeto é o escopo alvo. Dentro do bloco, você pode acessar e modificar diretamente as propriedades de objeto.

Características

  • Isolamento: entradas declaradas dentro de um Bloco Escopado são locais para aquele escopo e não afetam o escopo externo.
  • Acesso ao Escopo Externo: Blocos Escopados podem acessar entradas do escopo externo.

Exemplo

x = {}

x.{
  a = 5      # 'a' agora é uma propriedade de 'x'
  b = a + 3  # 'b' agora também é uma propriedade de 'x'
}

Interações de escopos

FatScript resolve nomes dinamicamente, percorrendo a pilha de chamadas ativa — não há escopo léxico. Esta seção explora esses mecanismos, incluindo a ordem de resolução de nomes, nuances de atribuição, comportamentos de incremento/decremento e o uso inovador do operador += para alternância de booleanos.

Resolução de nomes

Um nome livre é resolvido contra os frames ativos no momento em que o código executa:

  1. o frame atual (locais e parâmetros)
  2. o escopo vinculado ao método, quando houver (por exemplo, o módulo onde foi declarado, empilhado no momento da chamada)
  3. os frames ativos envolventes da pilha de chamadas, do mais próximo ao mais distante
  4. o escopo global (raiz), como último recurso

Uma chamada com ponto como holder.method(...) empilha o escopo do holder, e é por isso que funções de módulo enxergam os demais membros do módulo, e os argumentos dessas chamadas podem referenciar membros do holder diretamente.

a partir da v4.6.0, métodos declarados no nível superior de um programa não vinculam mais o escopo global: as declarações da raiz resolvem como último recurso, então parâmetros e locais de funções envolventes vencem entradas de mesmo nome no nível superior, e métodos de nível superior aplicados parcialmente (curried) leem as declarações da raiz ao vivo

Atribuição

O operador de atribuição (=) copia valores de escopos externos para o escopo atual, definindo um novo valor:

~ n = 1
x = {}
x.{ ~ n = n }  # agora x.n == 1, e x.n é independente de root.n
x.{ c = n }    # tem efeito semelhante, porém 'c' é imutável

o mesmo conceito se aplica ao código executado em um escopo de método

Capturando valores externos

Ao declarar um escopo em linha, você pode "capturar" valores do escopo externo simplesmente nomeando-os, sem precisar reatribuir:

a = 5
b = 6
meuEscopo = { a, b = 7 }

# meuEscopo == { a = 5, b = 7 }

Aqui, a é copiado do contexto externo no momento em que o escopo é criado. Essa técnica é útil quando você deseja construir escopos ou retornar objetos que referenciem parâmetros ou valores locais de forma concisa.

Ressalva

Usar ~ n = n + 1 dentro de um bloco ou método adiciona um novo 'n' no escopo atual, inicializado com o valor de n + 1 do escopo envolvente mais próximo, sem alterar o 'n' externo.

Incrementando e decrementando

Operações de incremento (+=) e decremento (-=) interagem com o escopo de variáveis de uma maneira diferente. Essas operações buscam a instância mais próxima de uma variável, começando do escopo atual e movendo-se para fora recursivamente, e então modificam essa instância diretamente.

~ outerN = 1
fn = -> {
  outerN += 1  # alveja e incrementa 'outerN' no escopo externo
}

Auto-inicialização com +=

FatScript também fornece um comportamento especial em relação ao operador de incremento (+=). Se não existir o incremento funciona como uma atribuição regular como se você tivesse escrito o seguinte para n += 1:

n == Void ? n = 1 : n += 1

O recurso de auto-inicialização pode ser particularmente útil quando usado em combinação com entradas dinâmicas para programação dinâmica.

este recurso está disponível exclusivamente para o operador de incremento, decremento não pode inicializar valores não existentes

Alternância de booleanos com +=

Geralmente, booleanos não permitem operações de adição. FatScript, no entanto, estende a funcionalidade do operador += para tipos booleanos, permitindo um mecanismo de alternância intuitivo dentro de escopos internos.

A expressão flag += !flag alterna efetivamente o valor booleano, mesmo quando flag é definido em um escopo externo.

no caso particular de booleanos, a única distinção entre = e += é o escopo

Outros operadores de atribuição compostos

Da mesma forma, outras operações de atribuição compostas, como *=, /=, %= e **=, são suportados por tipos numéricos e respeitam as mesmas regras de escopo que se aplicam às operações de incremento e decremento.

Veja também

results matching ""

    No results matching ""