Pular para o conteúdo

Match

Nesta página

match compara uma expressão contra padrões, de cima para baixo, e executa o primeiro que casar. Como o if, é uma expressão: o braço escolhido é o valor do match. O compilador exige que os casos sejam exaustivos.

A forma mais simples casa por valor literal — mais clara que uma cadeia de if/else if quando todos comparam a mesma expressão:

Tabela de despacho por número e por string; _ é o caso padrão.

11-match-literals.zolo
Playground
// Feature: `match` with literals

// Syntax: `match expr { lit1 => arm1, lit2 => arm2, _ => default }`

// When to use: dispatch table by concrete value

// (numbers, strings, bools). Clearer than a chain of

// `if/else if` when every branch compares the same expression.


let x = 3
let name = match x {
  1 => "one",
  2 => "two",
  3 => "three",
  _ => "other",
}
print("x = {name}")  // x = three


// Match with strings.

let day = "tue"
let lng = match day {
  "mon" => "Monday",
  "tue" => "Tuesday",
  "wed" => "Wednesday",
  "thu" => "Thursday",
  "fri" => "Friday",
  _ => "weekend",
}
print(lng)  // Tuesday


// Match returns a value — it's an expression.

fn http_label(code: int) -> str {
  return match code {
    200 => "OK",
    404 => "Not Found",
    500 => "Server Error",
    _ => "Unknown",
  }
}

print(http_label(200))  // OK

print(http_label(404))  // Not Found

print(http_label(418))  // Unknown

Vários valores no mesmo braço usam o padrão or (a | b):

a | b => … cobre múltiplos valores com um só braço.

13-match-or-patterns.zolo
Playground
// Feature: `match` with or-patterns

// Syntax: `pat1 | pat2 | pat3 => arm`

// When to use: group several cases that share the same

// body. Avoids repeating "=> ..." multiple times.


let day = "Saturday"
let kind = match day {
  "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" => "weekday",
  "Saturday" | "Sunday" => "weekend",
  _ => "unknown",
}
print("{day} is {kind}")  // Saturday is weekend


// Or-patterns with integers.

fn small_prime(n: int) -> bool {
  return match n {
    2 | 3 | 5 | 7 | 11 | 13 => true,
    _ => false,
  }
}

print(small_prime(7))  // true

print(small_prime(8))  // false

print(small_prime(13))  // true


// Combining many cases in one concise expression.

let ch = "u"
let kind2 = match ch {
  "a" | "e" | "i" | "o" | "u" => "vowel",
  _ => "consonant or other",
}
print(kind2)  // vowel

Faixas casam intervalos contíguos:

1..=5 => … casa qualquer valor na faixa.

14-match-ranges.zolo
Playground
// Feature: `match` with ranges

// Syntax: `start..=end => arm`  (inclusive)

//         `start..end  => arm`  (exclusive)

// When to use: classify a numeric value into continuous

// bands — age, score, time-of-day window, etc.


let age = 25
let group = match age {
  0..=12 => "child",
  13..=19 => "teenager",
  20..=64 => "adult",
  _ => "senior",
}
print("{age} -> {group}")  // 25 -> adult


// Score / report card.

let score = 85
let grade = match score {
  90..=100 => "A",
  80..=89 => "B",
  70..=79 => "C",
  60..=69 => "D",
  _ => "F",
}
print("{score} = {grade}")  // 85 = B


// Combination of literal + range.

let h = 14
let period = match h {
  0..=5 => "late night",
  6..=11 => "morning",
  12 => "noon",
  13..=17 => "afternoon",
  18..=23 => "evening",
  _ => "?",
}
print("{h}h -> {period}")  // 14h -> afternoon

Uma guarda adiciona uma condição extra ao braço:

x if x > 0 => … só casa quando a guarda é verdadeira.

15-match-guards.zolo
Playground
// Feature: `match` with guards

// Syntax: `pattern if cond => arm`

// When to use: refine a pattern with an arbitrary

// condition. Runs only if the pattern matches AND the

// condition is true. Replaces ranges/literals when the

// rule is dynamic.


let n = -5
let descr = match n {
  x if x < 0 => "negative: {x}",
  0 => "zero",
  x if x < 10 => "small positive: {x}",
  x => "large: {x}",
}
print(descr)  // negative: -5


// Guards using other variables in scope.

let limit = 100
let v = 250
let result = match v {
  x if x <= limit => "ok ({x})",
  x => "overflow ({x})",
}
print(result)  // overflow (250)


// Combining a guard with a range pattern.

let score = 87
let level = match score {
  s if s == 100 => "perfect",
  90..=99 => "excellent",
  s if s >= 70 => "ok ({s})",
  _ => "poor",
}
print(level)  // ok (87)

match também desestrutura structs e enums, ligando os campos:

Extrai campos do struct direto no padrão.

16-match-struct.zolo
Playground
// Feature: `match` with struct destructuring

// Syntax: `match s { Type { field1, field2, .. } => ... }`

// When to use: extract fields from a struct while

// branching. `..` ignores extra fields.


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

let p = Point { x: 0.0, y: 0.0, z: 5.0 }

let location = match p {
  Point { x: 0.0, y: 0.0, z: 0.0 } => "origin",
  Point { x, y: 0.0, z: 0.0 } => "X axis at {x}",
  Point { x: 0.0, y, z: 0.0 } => "Y axis at {y}",
  Point { x: 0.0, y: 0.0, z } => "Z axis at {z}",
  Point { x, y, z } => "point ({x},{y},{z})",
}
print(location)  // Z axis at 5


// Pick only the fields you need with `..`.

struct User {
  name: str,
  age: int,
  active: bool,
}

let u = User { name: "Alice", age: 30, active: true }
let label = match u {
  User { name, .. } => "hello {name}",
}
print(label)  // hello Alice

Cada variante do enum vira um braço — exaustivo por construção.

17-match-enum.zolo
Playground
// Feature: `match` with enum destructuring

// Syntax: `match val { EnumName::Variant(payload) => ... }`

// When to use: cover every variant of an enum

// (sum-type / tagged union). The compiler verifies that

// every case is handled (exhaustive).


enum Shape {
  Circle(float),
  Rectangle(float, float),
  Triangle(float, float, float),
}

fn area(s: Shape) -> float {
  return match s {
    Shape::Circle(r) => 3.14159 * r * r,
    Shape::Rectangle(w, h) => w * h,
    Shape::Triangle(a, b, c) => {
      // Heron's formula.

      let s = (a + b + c) / 2.0
      return s
    },
  }
}

print(area(Shape.Circle(2.0)))  // ~12.566

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


// Variant without payload + variant with payload in the same enum.

enum Maybe {
  Yes,
  No,
  Custom(str),
}

fn say(m: Maybe) -> str {
  return match m {
    Maybe::Yes => "yes",
    Maybe::No => "no",
    Maybe::Custom(txt) => "maybe: {txt}",
  }
}

print(say(Maybe.Yes))  // yes

print(say(Maybe.No))  // no

print(say(Maybe.Custom("depends")))  // maybe: depends

E padrões podem ser aninhados (enum dentro de enum, arrays):

18-match-nested.zolo
Playground
// Feature: `match` with nested patterns

// Syntax: patterns inside patterns

// When to use: match composite structures (enum inside

// enum, struct inside array, etc.) without doing it

// in two stages.


use std::Result

enum Result {
  Ok(int),
  Err(str),
}

enum Step {
  Start,
  Done(Result),
}

fn descr(s: Step) -> str {
  return match s {
    Step::Start => "starting",
    Step::Done(Result::Ok(n)) => "ok with {n}",
    Step::Done(Result::Err(msg)) => "error: {msg}",
  }
}

print(descr(Step.Start))  // starting

print(descr(Step.Done(Result.Ok(42))))  // ok with 42

print(descr(Step.Done(Result.Err("timeout"))))  // error: timeout


// Nested pattern in arrays.

let pairs = [[1, 2], [0, 0], [3, 4]]
for p in pairs {
  let m = match p {
    [0, 0] => "origin",
    [x, 0] => "X axis at {x}",
    [0, y] => "Y axis at {y}",
    [x, y] => "({x}, {y})",
    _ => "?",
  }
  print(m)
}
// expected:

// (1, 2)

// origin

// (3, 4)

Desafio

No exemplo de literais, troque o _ por uma faixa 400..=499 => "erro do cliente" e rode. O que acontece com a exaustividade?

Buscar no Zolo

9 resultados

enespt-br