Pular para o conteúdo

Desestruturação: Tuplas, Arrays, Structs e Enums

Nesta página

Padrões não servem apenas para literais: eles podem penetrar dentro de estruturas e extrair valores em um único passo, sem acesso manual por índice ou campo.

Tuplas e arrays em let

Em Zolo, a desestruturação posicional usa a forma let (a, b, c) = [...]. Os nomes recebem os valores na ordem, e o compilador verifica o tamanho. Funciona em let simples, em for e ao receber retornos de funções.

Desestruturação posicional em let, retorno de função e laço for.

08-tuple-destructure.zolo
Playground
// Feature: Tuple / array destructuring in `let`

// Syntax: `let (a, b, c) = [v1, v2, v3]`

// When to use: extract multiple values positionally. In Zolo,

// "tuples" at the value site are arrays.


// Basic form: 3 named values.

let (a, b, c) = [1, 2, 3]
print(a)  // 1

print(b)  // 2

print(c)  // 3


// Heterogeneous types: each slot can be a different type.

let (name, age, active) = ["Alice", 30, true]
print(name)  // Alice

print(age)  // 30

print(active)  // true


// Destructuring a function returning an array — min/max pattern.

fn min_max(arr: [int]) -> [int] {
  var lo = arr[0]
  var hi = arr[0]
  for x in arr {
    if x < lo { lo = x }
    if x > hi { hi = x }
  }
  return [lo, hi]
}

let (lo, hi) = min_max([3, 1, 4, 1, 5, 9, 2, 6])
print("lo={lo} hi={hi}")  // lo=1 hi=9


// Destructuring inside `for`.

let pairs = [[1, 2], [3, 4], [5, 6]]
for pair in pairs {
  let (l, r) = pair
  print("{l},{r}")
}
// expected:

// 1

// 2

// 3

// Alice

// 30

// true

// lo=1 hi=9

// 1,2

// 3,4

// 5,6

Padrões de array com ..

Além de destruturar um número fixo de elementos, você pode separar o primeiro (ou últimos) elemento(s) do resto com ..rest. A rest é um novo array. O .. sem nome simplesmente ignora os elementos restantes e serve para verificar a forma do array.

[first, ..rest], [a, b, ..], array vazio e checagem de comprimento mínimo.

09-array-patterns.zolo
Playground
// Feature: Array patterns with rest `..`

// Syntax: `[first, ..rest]`, `[a, b, ..]`, `[..init, last]`

// When to use: separate the first/last element(s) from the "rest"

// without index arithmetic.


let arr = [1, 2, 3, 4, 5]

// First + rest.

match arr {
  [first, ..rest] => print("first={first} rest_len={rest.len()}"),
  _ => print("empty"),
}

// First two + rest.

match arr {
  [a, b, ..rest] => print("a={a} b={b} rest_len={rest.len()}"),
  _ => print("fewer than 2"),
}

// Without naming the rest — only checks shape.

match arr {
  [_, _, ..] => print("has at least 2"),
  _ => print("does not have 2"),
}

// Empty array.

let empty: [int] = []
match empty {
  [] => print("really empty"),
  [_, ..] => print("has at least 1"),
}
// expected:

// first=1 rest_len=4

// a=1 b=2 rest_len=3

// has at least 2

// really empty

Desestruturação de structs

Dentro de um match, o padrão TipoStruct { campo1, campo2, .. } extrai campos pelo nome. O .. ignora os campos restantes sem precisar listá-los. Guardas podem ser adicionadas depois do padrão para refinar a seleção.

Extraindo campos de Point e Person; guarda sobre campo extraído.

10-struct-destructure.zolo
Playground
// Feature: Struct destructuring

// Syntax: `Type { field1, field2, .. }`

// When to use: extract specific fields from a struct inside a

// match or let. The `..` ignores the remaining fields.


struct Point {
  x: float,
  y: float,
  z: float,
}

let p = Point { x: 1.0, y: 2.0, z: 3.0 }

// Take everything by name.

match p {
  Point { x, y, z } => print("({x},{y},{z})"),
}

// Just some fields — `..` ignores the rest.

match p {
  Point { x, .. } => print("only x = {x}"),
}

match p {
  Point { y, z, .. } => print("y={y} z={z}"),
}

// Direct struct destructure in `let` is not yet supported in

// pattern position — use `match` when you need a full pattern,

// or field access (`p.x`) for the simple case.

print("p.x = {p.x}")
print("p.y = {p.y}")

// Match with guard on fields.

struct Person {
  name: str,
  age: int,
}

let alice = Person { name: "Alice", age: 17 }
let label = match alice {
  Person { age, .. } if age >= 18 => "adult",
  Person { age, .. } => "minor ({age})",
}
print(label)  // minor (17)

// expected:

// (1,2,3)

// only x = 1

// y=2 z=3

// p.x = 1

// p.y = 2

// minor (17)

Nota: a desestruturação direta de struct em let ainda não é suportada em posição de padrão — use match ou acesso por campo (p.x) nesses casos.

Desestruturação de enums

Cada variante de um enum pode carregar payload (posicional ou com campos nomeados). O padrão extrai esse payload diretamente. O match sobre um enum é exaustivo por construção: o compilador exige um braço para cada variante.

Shape com variantes tuple e struct; Event com payload nomeado.

11-enum-destructure.zolo
Playground
// Feature: Enum destructuring (with payload)

// Syntax: `Enum.Variant(x, y)` or `Enum.Variant { field }`

// When to use: extract values from each variant in a match.


enum Shape {
  Circle(float),
  Rect(float, float),
  Triangle {
    a: float,
    b: float,
    c: float,
  },
  Empty,
}

fn area(s: Shape) -> float {
  return match s {
    Shape::Circle(r) => 3.14159 * r * r,
    Shape::Rect(w, h) => w * h,
    Shape::Triangle { a, b, c } => {
      let semi = (a + b + c) / 2.0
      return semi
    },
    Shape::Empty => 0.0,
  }
}

print(area(Shape.Circle(5.0)))  // 78.53975

print(area(Shape.Rect(3.0, 4.0)))  // 12

// Struct-like variant constructor uses `::`.

print(area(Shape::Triangle { a: 3.0, b: 4.0, c: 5.0 }))  // 6

print(area(Shape.Empty))  // 0


// Enum with struct-like variants — named-field pattern.

enum Event {
  Click {
    x: int,
    y: int,
  },
  Key(str),
  Quit,
}

fn describe(e: Event) -> str {
  return match e {
    Event::Click { x, y } => "click at ({x},{y})",
    Event::Key(k) => "key {k}",
    Event::Quit => "quit",
  }
}

print(describe(Event::Click { x: 100, y: 200 }))
print(describe(Event.Key("Enter")))
print(describe(Event.Quit))
// expected:

// 78.53975

// 12

// 6

// 0

// click at (100,200)

// key Enter

// quit

Desafio

Adicione uma nova variante Point(float, float) ao enum Shape do exemplo de enums e trate-a na função area. Observe como o compilador avisa sobre exaustividade antes de você adicionar o braço.

Veja também

Buscar no Zolo

9 resultados

enespt-br