Slide 27 de 74

Casando com is

Variantes, e o que vinculam
type Shape {
	Circle    { radius: Int }
	Rectangle { width: Int, height: Int }
	Point
}

func describe(shape: Shape): Str {
	if shape is Shape.Circle(r) && r > 10 {
		return "um círculo grande"
	} else if shape is Shape.Circle(r) {
		return "um círculo de {r}"
	} else if shape is Shape.Rectangle(w, _) {
		return "um retângulo de {w} de largura"
	}
	return "um ponto"
}

proc main(): void {
	echo describe(Shape.Circle(40))
	echo describe(Shape.Circle(4))
	echo describe(Shape.Rectangle(3, 9))
	echo describe(Shape.Point())
}
Um nome em um padrão é sempre novo
proc main(): void {
	wanted := 3
	found := indexOf([5, 3, 1], 3)

	// Este `wanted` é um nome novo vinculado à posição que voltou:
	// ele esconde o de fora e não compara com nada.
	if found is Result.Ok(wanted) {
		echo "na posição {wanted}"
	}
	// Para testar um valor específico, escreva-o no lugar dele...
	if found is Result.Ok(1) {
		echo "a segunda, como esperado"
	}
	// ...ou vincule-o e compare.
	if found is Result.Ok(at) && at > 0 {
		echo "não é a primeira"
	}
	echo wanted            // 3 — o de fora, intocado
}

valor is Padrão é um Bool que é true quando o valor tem aquela forma, e vincula nomes para o que ele carrega. Não existe instrução match: um casamento é um if, ou uma cadeia if/else if testando um mesmo sujeito.

  • Um padrão de variante nomeia a variante e vincula seus campos por posição, os próprios da variante primeiro e os compartilhados depois: shape is Shape.Rectangle(w, h). Ele vincula todos os campos ou nenhum — Shape.Rectangle sozinho casa com qualquer retângulo — e _ pega um campo sem vinculá-lo.
  • Result.Ok(v) e Result.Error(e) também são padrões de variante.
  • Um nome em um padrão é sempre um nome novo: ele nunca é comparado com uma variável que já está no escopo. Para testar um valor específico, escreva o próprio valor no lugar dele — Result.Ok(1) — ou vincule-o e compare depois de &&.

Um nome vinculado por um casamento é imutável. Ele está no escopo do ramo que o casamento protege e no resto da mesma condição depois de && — if r is Result.Ok(n) && n > 10 — mas não em um else, e não depois de um ||, onde nada diz qual lado casou.