BDR é legal, mas um pouco caótico. Primeiro, os buggles balançam em todas as direções, o que faz com que o código que você tenha que escrever para fazê-los se mover seja um pouco difícil de ler. Apresentamos agora um novo mundo DBR onde os buggles dançam num suave círculo. Vamos aproveitar esta tranquilidade para limpar um pouco nosso código graças a novas construções que vamos introduzir.
switch
[/!][!scala]busca de padrões[/!]A parte mais difícil do código anterior é comn certeza a cascata de condicionais. Em algum ponto do seu código, você certamente tem algo como isto:
if ([!java|c]getIndicação() == 'R'[/!][!scala]lerMensagem() == "R"[/!]) {
direita();
[!c]avançarUmPasso()[/!][!java|scala]avançar()[/!];
} else if ([!java|c]getIndicação() == 'L'[/!][!scala]lerMensagem() == "L"[/!]) {
esquerda();
[!c]avançarUmPasso()[/!][!java|scala]avançar()[/!];
} else if ([!java|c]getIndicação() == 'I'[/!][!scala]lerMensagem() == "I"[/!]) {
voltar();
[!c]avançarUmPasso()[/!][!java|scala]avançar()[/!];
/* other else if */
} else {
terminou = [!c]1[/!][!java|scala]true[/!];
}
When you review this code, it may not be clear at the first glance that it
is simply a choice with 4 branches depending on the value of
[!java|c]getIndication()[/!][!scala]readMessage()[/!]. To improve this, we
will use a [!java|c]switch
construct, which Java syntax is the
following:[/!] [!scala] pattern matching, which is a very powerful construct
that greatly generalizes the if
. It is arguably one of the
major advantages of Scala when compared to languages such as Java or
python. It is not new either, as other languages such as OCaml or Haskell
offer this feature since long, but still. It's really cool![/!]
switch (expression) { case firstValue: whatToDoIfExpressionEqualsFirstValue(); break; case secondValue: whatToDoIfExpressionEqualsSecondValue(); break; case thirdValue: whatToDoIfExpressionEqualsThirdValue(); break; /* as much similar cases as you want */ default: whatToDoIfExpressionDoesNotEqualsAnySeenValues(); }
Observe que cada ramo de um switch deve terminar com um
break
. se você esquecer dele, a máquina continua e
executa o próximo ramo na lista depois do ramo para o qual ele
pulou. Existem na verdade uns raros casos onde este
comportamento é útil.
É então possível reescrever o código do BDR anterior numa forma mais clara usando a construção switch:
switch (getIndicação()) { case 'R': direita(); [!c]avançarUmPasso()[/!][!java]avançar()[/!]; break; case 'L': esquerda(); [!c]avançarUmPasso()[/!][!java]avançar()[/!]; break; case 'I': voltar(); [!c]avançarUmPasso()[/!][!java]avançar()[/!]; break; default: return; }[/!] [!scala]
expressão match { case um valor possível => instruções case um outro valor => outras instruções case mais outro valor => e outras instruções case _ => instruções padrão }
A espressão fornecida antes da palavra-chave match
, e os
ramos seguintes são avaliados um após o outro até encontrarmos um cujo
valor fornecido entre case
e =>
seja igual
ao valor da expressão. O símbolo _
age como um coringa,
logo o ramo _
sempre casa. Aqui está um exemplo de
onde uma variável name
casa.
name match { case "Martin" => println("Oi Martin, como vai?") case "Gerald" => println("Oi Gerald! como vai você?") case _ => println("Olá estranho.") }
é possível ter mais que uma instrução por ramo, e mesclar ramos quando os valores são separados por um símbolo | .
name match { case "Martin" | "Gerald" => println("Oi "+name+", como vai?"); openTheDoor() case _ => println("Oi estranho. Favor não passar."); lockTheDoor() }
You can even add guards to your branches. These are extra conditions that must be respected for the branch to get applied. This is handy if you want match on value ranges, as follows.
age match { case i if i<10 => println("Oi menino!") case i if i<20 => println("Oi cara!") case i if i<30 => println("Oi, meu caro") case _ => println("Oi senhor") }
Observe que não há necessidade de verificar se o valor é maior que 10 na segunda linha por que o primeiro ramo "foi verificado". Então, se o segundo ramo está sendo verificado, o primeiro não aprovou.
Finalmente, é possível também aprovar várias variáveis de uma vez!
(x,y) match { case (0,0) => println("Esta é a origem") case (_,0) => println("nas ordenadas") case (0,_) => println("nas abscissas") case (_,_) => println("algum ponto qualquer") }
Eu disse que reconhecimentod e padrões em scala é muito poderoso! Eu adoro esta funcionalidade!
[/!][!java|scala|c]"Aplique" a melhoria que acabamos de ver para reescrever seu código do buggle com os seguintes passos de dança. [/!] [!python]Vamos ensinar um novo passo de dança para os buggles. É um pouco mais complexo mas na verdade vai ficar mais legal. Apesar disto, é a mesma história de sempre.[/!] Observe que nósagora vamos subir seis células em um passo de dança.
Mensagem | O que fazer |
[!java|c]'R'[/!][!scala|python]"R"[/!] | Vire a direita (R de right) e mova um passo a frente |
[!java|c]'L'[/!][!scala|python]"L"[/!] | Vire a esquerda e mova um passo a frente |
[!java|c]'I'[/!][!scala|python]"I"[/!] | Vire e dê um passo para frente |
[!java|c]'A'[/!][!scala|python]"A"[/!] | Mova um passo a frente |
[!java|c]'B'[/!][!scala|python]"B"[/!] | Mova dois passos a frente |
[!java|c]'C'[/!][!scala|python]"C"[/!] | Mova três passos a frente |
[!java|c]'D'[/!][!scala|python]"D"[/!] | Mova quantro passos para frente |
[!java|c]'E'[/!][!scala|python]"E"[/!] | Mova cinco passos para frente |
[!java|c]'F'[/!][!scala|python]"F"[/!] | Mova seis passos para frente |
[!java|c]'Z'[/!][!scala|python]"Z"[/!] | Mova um passo para trás |
[!java|c]'Y'[/!][!scala|python]"Y"[/!] | Mova dois passos para trás |
[!java|c]'X'[/!][!scala|python]"X"[/!] | Mova três passos para trás |
[!java|c]'W'[/!][!scala|python]"W"[/!] | Mova quatro passos para trás |
[!java|c]'V'[/!][!scala|python]"V"[/!] | Mova cinco passos para trás |
[!java|c]'U'[/!][!scala|python]"U"[/!] | Mova seis passos para trás |
(qualquer outra coisa) | Parar de dançar. |
Quando seu programa funcionar de novo, vá para o próximo exercício.