Em Elixir o pattern matching não está apenas associado com variáveis, mas também com function, podemos utilizar pattern matching em nossas functions, tornando nossas functions específica para cada situação.
Vamos pensar em um jogo de adivinhação, queremos criar um jogo onde podemos adivinhar um número secreto. Com base no número que você recebe como palpite, você pode ter as seguintes saídas:
Condição | Respostas |
---|---|
Quando o palpite corresponde ao número secreto | Correto |
Quando o palpite é um a mais ou um a menos que o número secreto | Próximo |
Quando o palpite é maior que o número secreto | Maior |
Quando o palpite for menor que o número secreto | Menor |
Quando um palpite não é feito | Faça um palpite |
- Todas as suposições e números secretos são números inteiros.
O nosso programa tem as seguintes regras:
1. Dê resposta quando o palpite corresponder ao número secreto
Vamos implementar a função compare/2
que recebe dois argumentos, secret_number
e guess
, que são ambos inteiros.
GuessingGame.compare(5, 5)
# => "Correto"
2. Dê resposta quando o palpite for maior que o número secreto
Nesta situação queremos que a função de comparação responda com Maior
.
GuessingGame.compare(5, 8)
# => "Maior"
3. Dê resposta quando o palpite for menor que o número secreto
Nesta situação queremos que a função de comparação responda com Menor
.
GuessingGame.compare(5, 2)
# => "Menor"
4. Dê respostas quando o palpite for um a mais ou um a menos que o número secreto
Nessa situação se o valor inserido tiver diferença de 1 seja para maior ou menor queremos que a função de comparação responda com Próximo
GuessingGame.compare(5, 6)
# => "Próximo"
GuessingGame.compare(5, 4)
# => "Próximo"
5. Dê resposta quando não houver palpite
Nessa situação queremos que quando não houve palpite, a função compare responda com Faça um palpite
GuessingGame.compare(5)
# => "Faça um palpite"
GuessingGame.compare(5, :no_guess)
# => "Faça um palpite"
E como podemos resolver este problema? Como falamos anteriormente o Elixir possui um Pattern Matching que também podemos usar em functions. Então, para iniciar nossa implementaçao vamos começar pela parte onde não enviamos palpite.
Inicialmente vamos começar com a function que recebe apenas 1 parâmetro, vamos definir a nossa function para retornar exatamente o que esperamos, que é uma string: “Faça um palpite”
defmodule GuessingGame do
def compare(secret_number), do: "Faça um palpite"
end
Ok, assim sabemos que ao chamar a function GuessingGame.compare(1)
por exemplo, receberemos como retorno a frase "Faça um palpite”
iex(1)> GuessingGame.compare(1)
"Faça um palpite"
Mas também queremos que quando executarmos GuessingGame.compare(1, :no_guess)
também receber o mesmo resultado. Para solucionar esse problema vamos precisar utilizar do default value e também do when.
Em Elixir, podemos definir parâmetros em nossas functions com valores defaults e com when
podemos escolher que function executar a partir desta condição. Levando isto em consideração, nossa solução final facaria assim:
defmodule GuessingGame do
def compare(secret_number, guess \\ :no_guess)
def compare(secret_number, guess) when guess == :no_guess, do: "Faça um palpite"
end
E o resultado seria como este:
iex(1)> GuessingGame.compare(1)
"Faça um palpite"
iex(2)> GuessingGame.compare(1, :no_guess)
"Faça um palpite"
Agora, para atender as demais questões levantadas em nosso sistema, podemos utilizar o when para definir as demais funções e solucionar nosso problema.
defmodule GuessingGame do
def compare(secret_number, guess \\ :no_guess)
def compare(secret_number, guess) when guess == :no_guess, do: "Faça um palpite"
def compare(secret_number, guess) when secret_number == guess, do: "Correto"
def compare(secret_number, guess) when secret_number - 1 == guess, do: "Próximo"
def compare(secret_number, guess) when secret_number + 1 == guess, do: "Próximo"
def compare(secret_number, guess) when secret_number > guess, do: "Menor"
def compare(secret_number, guess) when secret_number < guess, do: "Maior"
end
Top comments (0)