Pular para o conteúdo

Desestruturação

Extrair vários valores de uma vez, por posição ou por nome.

Por posição#

dataforge
a, b := [1, 2]
x, y, z := [10, 20, 30]

out a, b, x + y + z

O lado direito é percorrido e cada elemento vai para o nome correspondente.

A troca sem temporária#

dataforge
p := "primeiro"
q := "segundo"
p, q := q, p
out p, q

O lado direito é avaliado inteiro antes de qualquer atribuição acontecer. Por isso não há variável temporária nem risco de sobrescrever p antes de ler.

Quantidade errada falha#

dataforge
m, n := [1, 2, 3]
# Cannot unpack 3 value(s) into 2 name(s)

Isso é deliberado. Um [1, 2, 3] chegando onde se esperavam dois valores quase sempre significa que a suposição sobre os dados estava errada — e falhar alto é melhor que descartar o 3 em silêncio.

Com ...resto#

dataforge
primeiro, ...outros := [1, 2, 3, 4, 5]
out primeiro, outros            # 1 [2, 3, 4, 5]

inicio, ...meio, fim := [1, 2, 3, 4, 5]
out inicio, meio, fim           # 1 [2, 3, 4] 5

so_um, ...nada := [9]
out nada                        # [] — resto vazio é válido

Só é permitido um ...resto por desestruturação — com dois, não haveria como saber onde um termina e o outro começa.

Por nome#

Com chaves, a desestruturação passa a ser por nome, e a ordem não importa:

dataforge
record Usuario:
    nome: String
    idade: Integer
    cidade: String

u := Usuario("Ana", 30, "Floripa")
{nome, cidade} := u
out $"{nome} mora em {cidade}"

config := {"host": "localhost", "porta": 8080}
{host, porta} := config
out $"{host}:{porta}"
FormaCasa porFonte
a, b := …posiçãolista, record
{a, b} := …nomevault, record, instância

Chave ausente falha#

text
Vault has no key 'inexistente' to destructure. Keys: host, porta, debug

A mensagem lista as chaves que existem — quase sempre o erro é um nome digitado errado, e ver a lista resolve na hora.

Resto nomeado#

dataforge
{nome, ...resto} := u
out resto        # {idade: 30, cidade: Floripa}

Útil para "pegue esses dois campos e passe o resto adiante" — um padrão comum ao tratar requisições HTTP.

Desempacotar no início da ação#

dataforge
action apresentar(pessoa):
    {nome, idade} := pessoa
    yield $"{nome}, {idade} anos"

Duas vantagens sobre usar pessoa.nome no corpo inteiro: a primeira linha documenta o que a ação consome, e o resto do corpo fica mais curto.

Retornar vários valores#

DataForge não tem tuplas separadas de listas. Devolver vários valores é devolver uma lista, e quem chama desestrutura:

dataforge
action divide_com_resto(a, b):
    yield [a ~/ b, a % b]

quociente, resto := divide_com_resto(17, 5)
out $"17 / 5 = {quociente} resto {resto}"

Isso lê melhor que resultado[0] e resultado[1] espalhados pelo código.

Comparando#

DataForgeJavaScriptPython
a, ...r := listaconst [a, ...r] = listaa, *r = lista
{a, b} := objconst {a, b} = obj