# Haskell/Casamento de padrões, if e let

* Casamento de padrões, if e let
* Introdução
* Primeiro passo
* Variáveis e funções
* Verdadeiro ou falso
* Tipos básicos
* Listas e n-uplas
* Tipos básicos II
* Casamento de padrões, if e let
* Composição de funções
* Entradas e saídas simples
Este capítulo introduz expressões if, casamento de padrões e a palavra-chave let.

## if / then / else

Haskell suporta expressões de condicionais simples, da forma se x então p senão q. A estrutura é a mesma que a de muitas linguagens de programação. Por exemplo, considere uma função que: retorna -1 e seu argumento for menor 0; 0 se o argumento for igual a 0; ou 1 se o argumento for maior que 0:
O fato é que Haskell já possui a função signum que faz exatamente isso, mas vamos usá-la para exemplificar expressões condicionais.
Em qualquer expressão if (if em inglês significa "se"), a primeira condição e avaliada: se ela for verdadeira, a expressão dentro de then (then em inglês significa "então") é avalidada; se ela for falsa, a expressão dentro de else (else em inglês significa "senão"), que pode ou não existir, é avaliada.
No caso de minhaSignum:
* A condição avaliada é x < 0.
* Se a condição retornar um Bool True, a expressão dentro de then é avaliada: a função minhaSignum retornará -1
* Se a condição retornar um Bool False, a expressão dentro de else é avaliada: uma nova expressão if then else deve ser avaliada.
** A condição avaliada é x > 0.
** Se a condição retornar um Bool True, a expressão dentro de then é avaliada: a função minhaSignum retornará 1;
** Se a condição retornar um Bool False, a expressão dentro de else é avaliada: a função minhaSignum retornará 0.
Aqui tivemos o exemplo de duas expressões condicionais aninhadas, isto é, uma dentro de outra, o que é perfeitamente possível e bastante comum em programação.
Qualquer função que precise usar expressões condicionais também pode ser escrita usando guardas:
Da mesma forma, qualquer função que use guardas também pode ser escrita com expressões se explícitas. Vejamos a função absoluto que definimos em Verdadeiro ou falso:
Mas por que há duas maneiras de se escrever expressões condicionais? Por que não usar somente if ou somente guardas? Apesar de serem a mesma coisa, com o mesmo desempenho computacional, sua experiência lhe dirá qual das duas formas é mais legível. Não há melhor ou pior, só mais ou menos legível.

### Tipos numa expressão condicional

É importante observar os tipos das expressões usadas dentro de if / then / else:
* As condições avaliadas por if devem sempre retornar um Bool.
* Os valores finais das expressões dentro de then e else, podem ser de qualquer tipo, mas ambos devem ser do mesmo tipo.
Esta é uma função válida em Haskell:
Esta é uma função inválida em Haskell:

#### Exercício

Por que as expressões dentro de then e else contidas num mesmo if devem possuir o mesmo tipo?

## Casamento de padrões: introdução

Considere um programa que analisa dados estatísticos de uma competição de corrida na qual cada piloto recebe pontos de acordo com sua posição final. As regras são:
* 1° lugar: 10 pontos
* 2° lugar: 6 pontos
* 3° lugar: 4 pontos
* 4° lugar: 3 pontos
* 5° lugar: 2 pontos
* 6° lugar: 1 pontos
* Nenhum ponto para os demais.
Podemos escrever uma função que recebe a classificação final de um piloto (representada por um número inteiro), e que retorna quantos pontos devem ser creditados.
Por simplicidade, não vamos nos preocupar com o que aconteceria se o argumento fosse um número negativo, ou zero, por exemplo. Entretanto, numa aplicação real, deve-se sempre pensar nestes casos improváveis. Aqui simplesmente dissemos que o resultado é 0 para qualquer argumento que não seja maior que ou igual a 1 e menor que ou igual a 6.
Observe função que acabamos de escrever. Ela contem seis expressões ifaninhadas. Mesmo podendo copiar e colar texto, esta implementação ainda é propensa a erros, além de ser difícil de entender. Poderíamos escrever usando guardas, o que seria um pouco melhor, mas ainda seria necessário escrever todos os seis testes de igualdade. Fica como exercício.

### Exercício

Reescreva a função pts usando guardas.
Uma maneira muito mais fácil e legível seria:
Muito melhor. Faça o teste desta nova implementação e veja que funciona da mesma forma que o método anteiror.
O acontece aqui é o que chamamos de casamento de padrões. Quando a função é chamada com um certo argumento x, o compilador vai buscar qual dos padrões de argumentos mostrados do lado esquerdo são iguais a x. Quando encontrar, vai executar a expressão do lado direito:
* Ao executar pts 3, o comiplador passará por pts 1, pts 2 e chegará a pts 3.
* Como o argumento de chamada é igual ao argumento do padrão, (3 == 3), a expressão do lado direito é executada, e a função retorna 4.
É bastante comum que o último padrão use _ como argumento para indicar qualquer valor, isto é, se o padrão não se encaixar em nenhum caso anterior, então se encaixará no caso em que qualquer valor é válido:
* Ao executar pts 0, o comiplador passará por pts 1, pts 2, pts 3, pts 4, pts 5, pts 6 e chegará a pts _.
* Como _ indica qualquer valor e 0 é um valor qualquer, a expressão do lado direito é executada, e função retorna 0.
A ordem dos padrões é importante para a execução correta da função. Verifique você mesmo o que acontece se o padrão _ for definido entre 2 e 3, por exemplo. Ignore qualquer mensagem de erro que possa aparecer e tente executar pts 5.
Perceba que não usamos nenhuma varíavel na definição de pts, apenas valores. Isso é perfeitamente possível, uma vez que todos os valores retornados são constantes. Entretanto, olhando mais de perto, pts obedece a seguinte fórmula matemática:
${\text{pts}}(x)={\begin{cases}10,&{\mbox{se }}x=1\\6,&{\mbox{se }}x=2\\7-x,&{\mbox{se }}2<x\leq 6\\0,&{\mbox{se }}x>6\end{cases}}$
A notação matemática já nos dá uma indicação do que podemos tentar: misturar casamento de padrões e guardas. De fato, Haskell nos permite fazer exatamente isso:
Fica fácil perceber que agora, em vez de usarmos _ para capturar qualquer padrão não especificado, temos otherwise fazendo isso.

### Exercício

A versão de casamento de padrões de pts e esta última versão mista são ligeiramente diferentes. Você consegue ver a diferença? Conseguiria reescrever a versão mista para que as duas retornem os mesmos resultados sempre? Dica: compare a definição matemática e a implementação em Haskell e preste atenção a condição implícita da definição matemática.
Além de número inteiros, casamento de padrões funciona qualquer tipo de dado. Um bom exemplo é o operador lógico ou, (||), que vimos em Verdadeiro ou falso. Ele poderia ser definido como sendo:
ou
Ou ainda:
Se usarmos casamento de padrões em funções de mais de um argumento, as expressões só serão avaliadas se todos os argumentos se encaixarem em algum padrão. E se os argumentos não se encaixarem em nenhum padrão, teremos um erro de execução. Por isso, como dito anteriormente, é sempre bom ter um caso _ ou otherwise para capturar padrões inesperados ou indesejados.
Vejamos um exemplo de padrão que não funciona. A função lógica E não poderia ser definida assim:
Mesmo que usemos x nos dois argumentos para indicar que eles devem ser iguais, o compilador não compara argumentos entre si. A primeira linha é, portanto, equivalente a segunda. Além disso, ainda teremos um erro do compilador dizendo que x foi definido múltiplas vezes.

## Padrões com n-uplas e listas

Os exemplos anteriores mostram que usar casamento de padrões para escrever funções resultam num código muito mais legível e elegante. Entretanto, eles não ilustram por que este método é tão importante. Primeiro, considere que você precisa implementar a função fst, que extrai o primeiro elemento de uma dupla. Esta parece ser uma tarefa impossível com os conhecimentos básicos de Haskell, já que a única maneira de acessar o primeiro elemento de uma dupla é usando a própria função fst. Entretanto, veja a função fst' a seguir, que realiza o mesmo trabalho que fst:
Parece mágica, mas é apenas casamento de padrões com n-uplas (uma dupla, neste caso). Em fst', se aplicarmos um argumento (1,2), por exemplo, o primeiro elemento 1 seria associado a variável x, enquanto que 2 seria associado a _ e descartado. Depois disso, pode-se fazer qualquer operação com x do lado direito.

### Exercício

Escreva uma função quarto que extraia o quarto elemento de uma 10-upla.
Um padrão semelhante pode ser usado em listas. Vejamos a definição de head e tail
A lista, assim como uma dupla, é dividia em dois elementos: cabeça e cauda. A cabeça é o elemento que aparece à esquerda do cons ((:)), e a cauda, o que aparece à direita. No caso de head e tail, ainda precisamos de um padrão específico para o caso de uma lista vazia, o qual usa a função error para exibir uma mensagem de erro durante a execução da aplicação.
Resumindo, a verdadeira vantagem de usar casamento de padrões é o fato de facilitar o acesso a valores contidos em estruturas de dados mais complexas. Casamento de padrões com listas são bastante usados em Haskell, especialmente em funções recursivas, como veremos no capítulo Recurssão.

## Associações let

Para concluirmos, uma breve introdução a associações let, que nada mais são que uma alternativa ao uso de where, sendo elas intercambiáveis muitas das vezes.
A sintaxe de where é: <expressões> where <associações>. No caso de let, temos o contrário: let <associações> in <expressões>. Para se lembrar melhor, basta traduzir do inglês: seja <associações> em <expressões>.
Vejamos um problema simples: encontrar as soluções da equação $ax^{2}+bx+c=0$. A soluções são dadas por: $x={\frac {-b\pm {\sqrt {b^{2}-4ac}}}{2a}}$. Uma função para calcular a dupla de soluções de $x$ poderia ser:
Perceba a repetição de sqrt(b * b - 4 * a * c). Poderíamos usar where para definir raizDelta = sqrt(b * b - 4 * a * c) uma única vez na função:
Ou podemos usar let:

## Notas

* ↑ Se você já tem experiência com outras linguagens, já deve ter usado elseif ou algo parecido. Em Haskell, entretanto, não há esta funcionalidade, portanto precisamos aninhar as expressões de forma explícita.