Pattern Matching (Correspondência de Padrões ou Casamento de Padrões) é uma técnica muito utilizada por linguagens funcionais para desconstruir estruturas complexas. A princípio a técnica pode até parecer estranha, mas aos poucos você percebe a grande importância e logo não consegue mais viver sem ela. Vamos conhecê-la?
Para entender sobre Pattern Patching a primeira coisa que precisamos entender é o Match Operator, que comumente usamos em outras linguagens como operador de atribuição ou seja o igual (=). Veja esse exemplo:
iex(1)> n1 = 1
1
iex(2)> 1 = n1
1
iex(3)> 2 = n1
** (MatchError) no match of right hand side value: 1
Perceba que na primeira linha entendemos que n1 “recebe” 1, ou “atribui” 1. Só que na verdade, como o igual (=), no Elixir, não é o operador de atribuição e sim um operador de “match / correspondência / casamento”, o que ocorre é que o compilador “faz uma pergunta” mais ou menos assim…
A variável n1 pode ser correspondida com o valor 1?
Se isso for verdade, n1 apontará para 1 nas próximas instruções. Ou seja, isso quer dizer que será criado um vínculo entre a variável n1 e o número 1. E aqui já podemos notar uma diferença entre “n1 receber 1” e “n1 apontar para 1”, visto que “apontar” significa que a variável de fato é apenas um ponteiro que indica onde o valor apontado está. Veja essa figura:

Caso você não tenha entendido a figura acima, recomendo ler esse post onde falo sobre listas e tuplas, blz?
Agora vamos para a segunda linha do código (1 = n1)… O costume seria ler “1 recebe n1”, não é mesmo? Mas, por se tratar do operador match, lemos:
1 pode ser correspondido com N1?
iex(2)> 1 = n1
1
E nesse caso também é verdadeiro pois o n1 já aponta para 1 e vice-versa (conforme podemos observar na figura anterior).
Agora, na terceira linha (2 = n1) vemos algo diferente. A pergunta é…
2 pode ser correspondido com N1?
iex(3)> 2 = n1
** (MatchError) no match of right hand side value: 1
E observamos que um erro é levantado informando que …
“Não há correspondência com o lado da mão direita valor: 1”
Nesse momento há algo importante de se entender…
Match Operator
O Match Operator (=) é um operador binário, ou seja, ele precisa ter dois elementos para serem avaliados (um de cada lado). Sendo assim. Veja:

No Elixir, o Match Opertor, após a avaliação de correspondência, caso o resultado seja válido, sempre fará a atribuição na mão esquerda. Sendo assim, na linha 3 do nosso exemplo (2 = n1), o Elixir verifica que n1 aponta para o valor 1 e que 1 não corresponde a 2, e como a atribuição é feita sempre do lado esquerdo, por 2 não ser uma variável, não é possível uma reatribuição também.
Agora veja a continuação do exemplo…
iex(1)> n1 = 1
1
iex(2)> 1 = n1
1
iex(3)> 2 = n1
** (MatchError) no match of right hand side value: 1
iex(4)> n2 = n1
1
iex(5)> n2
1
Na linha 4, usamos o Match Operator…
“N2 pode ser correspondido com N1?”
E nesse caso, como n2 é uma variável, ela pode ser atribuída e passou a apontar para o mesmo local de n1, ou seja, o valor 1.

Pattern Matching
Agora, que já entendemos o Match Operator, vamos brincar com o Pattern Matching, que tem o mesmo princípio mas pode ser aplicado a estruturas mais complexas. Veja esse exemplo…
iex(1)> {a, b, c} = {:jackson, "pires", 123}
{:jackson, "pires", 123}
iex(2)> a
:jackson
iex(3)> b
"pires"
iex(4)> c
123
Perceba no exemplo acima, do lado esquerdo temos uma tupla constituídas apenas de variáveis, e do lado direito uma tupla com alguns valores.
Nesse momento, o Elixir verifica…
As estruturas podem ser correspondidas? — Sim pois as duas são tuplas. O primeiro elemento da tupla esquerda pode ser correspondido com o primeiro elemento da tupla direita? — Sim! O segundo elemento do lado esquerdo pode ser correspondido com o segundo elemento do lado direito? — Sim! E o terceiro? — Também!
Sendo assim, cada uma das variáveis, A, B e C serão apontadas cada um para seus respectivos valores isolados da tupla. E é isso que chamamos de “desconstruir” um tipo de dado complexo.
Observe abaixo que caso as estruturas não sejam equivalentes (em termos de quantidade de elementos ou de tipo de estrutura), o Pattern Matching não funciona.
iex> {a, b, c} = {:jackson, "pires"}
** (MatchError) no match of right hand side value: {:jackson, "pires"}
iex> {a, b, c} = [:jackson, "pires", 123]
** (MatchError) no match of right hand side value: [:jackson, "pires", 123]
Outra coisa interessante que podemos usar com Pattern Matching é a estrutura de cabeça e cauda para listas (como também já vimos aqui). Veja:
iex(1)> [cabeca | cauda] = [1, 2, 3]
[1, 2, 3]
iex(2)> cabeca
1
iex(3)> cauda
[2, 3]
Simples, não? 🙂
Bom, por enquanto é isso, pessoal. Espero que tenham gostado e entendido a real necessidade de se usar Pattern Matching.
Vamos ficando por aqui, e como sempre, não se esqueçam de nos acompanhar nas redes sociais, curtir nossa página no Facebook e se inscrever em nossa newsletter semanal.
É isso! Até a próxima! 😉
Referência: https://elixir-lang.org/getting-started/pattern-matching.html