## Buggle Dance Revolution 2 (BDR2)

[!java|scala|c]

Il BDR è bello ma è un po' caotico. Prima di tutto i buggles scorrazzano in tutte le direzioni e dopo il codice che si dovrà scrivere per farli muovere risulterà piuttosto difficile da leggere. Quì c'è un nuovo mondo BDR dove i buggle danzeranno dolcemente in cerchio. Approfitteremo di questa tranquillita per pulire un po' il vostro codice grazie al nuovo costrutto che introdurremo.

### [!java|c]`switch` conditionals[/!][!scala]Pattern matching[/!]

La parte difficile del codice precedente era sicuramente la cascata di condizioni. Da qualche parte nel vostro codice sicuramente avrete avuto qualcosa di simile ad:

    if ([!java|c]getIndication() == 'R'[/!][!scala]readMessage() == "R"[/!]) {
      right();
      [!c]stepForward()[/!][!java|scala]forward()[/!];
    } else if ([!java|c]getIndication() == 'L'[/!][!scala]readMessage() == "L"[/!]) {
      left();
      [!c]stepForward()[/!][!java|scala]forward()[/!];
    } else if ([!java|c]getIndication() == 'I'[/!][!scala]readMessage() == "I"[/!]) {
      back();
      [!c]stepForward()[/!][!java|scala]forward()[/!];
    /* other else if */
    } else {
      finished = [!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![/!]

[/!] [!java|c]

    switch (espressione) {
      case primoValore:
        cosaFareSeLespressioneCombaciaColPrimoValore();
        break;
      case secondoValore:
        cosaFareSeLespressioneCombaciaColSecondoValore();
        break;
      case terzoValue:
        cosaFareSeLespressioneCombaciaColTerzoValore();
        break;
        /* tutti i casi simili che vuoi */
      default:
        cosaFareSeLespressioneNonCombaciaConNessunValore();
    }

Osserva che ogni alternativa dello `switch` deve finire con un `break`. Se ve lo dimenticate il pc andra avanti ad eseguire l'alternativa successiva a quella cui si è balzati. Ci sono anche alcuni rari casi dove questo comportamento può rivelarsi utile.

È poi possibile riscrivere il precedente codice BDR in modo più pulito utilizzando il costrutto `switch`.

    switch (getIndication()) {
      case 'R':
        right();
        [!c]stepForward()[/!][!java]forward()[/!];
        break;
      case 'L':
        left();
        [!c]stepForward()[/!][!java]forward()[/!];
        break;
      case 'I':
        back();
        [!c]stepForward()[/!][!java]forward()[/!];
        break;
      default:
        return;
    }

[/!] [!scala]

    espressione match {
      case valore possibile => istruzioni
      case altro valore     => altre istruzioni
      case un altro valore => ancora altre istruzioni
      case _                 => istruzioni predefinite
    }

All'inizio viene valutata l'espressione posta prima della parola chiave `match` e subito dopo quelli delle alternative fintantoché non si trova il valore poste fra `case` ed `=>` uguale a quello dell'espressione. Il simbolo `_` agisce come jolly in modo che l'alternativa `_` sia sempre valida. Ecco un esempio dove una variabile `name` è comparata.

    name match {
      case "Martin" => println("Ciao Martin, come stai?")
      case "Gerald" => println("Hey Gerald! How are you doing?")
      case _            => println("Benvenuto straniero.")
    }

È possibile avere più di una istruzione per alternativa ed unire più alternative separando i valori con il simbolo | .

    name match {
      case "Martin" | "Gerald" => println("Ciao "+name+", come stai?"); openTheDoor()
      case _                            => println("Ciao straniero. Per piacere non passare."); chiudiLaPorta()
    }

Puoi anche aggiungere protezioni alle tue alternative. Queste sono condizioni extra che devono essere rispettate perché l'alternativa venga applicata. È utile quando volete comparare intervalli di valori, come nell'esempio seguente.

    anni match {
      case i if i<10 => println("Hey bambino!")
      case i if i<20 => println("Hey ragazzo!")
      case i if i<30 => println("Salve giovane uomo")
      case _           => println("Salve Signore")
    }

Nota che non c'è bisogno di controllare se il valore è più alto di 10 nella seconda riga perché le alternative sono considerate in ordine. Quindi, se la seconda alternativa viene valutata vuol dire che la prima non ha avuto corrispondenza.

Finalmente è possibile anche confrontare più variabili in un sol colpo!

    (x,y) match {
     case (0,0) => println("questa è l'origine")
     case (_,0) => println("On the ordinate")
     case (0,_) => println("Sulle ascisse")
     case (_,_) => println("Alcuni punti casuali")
    }

Io vi dicevo che il pattern matching di scala è veramente potente! Io attualmente amo questa caratteristica!

[/!]

### Traguardo dell'esercizio

[!java|scala|c]Apply the improvement we just saw to rewrite your buggle code with the following dance steps. [/!] [!python]Let's teach a new dance step to the buggles. It is slightly more complex but actually better looking. Beside of that, that's the same old story.[/!] Note that we can now move up to 6 cells in one dance step.

Messaggi | Cosa fa
[!java|c]'R'[/!][!scala|python]"R"[/!] | Gira a destra e muoviti un passo in avanti
[!java|c]'L'[/!][!scala|python]"L"[/!] | Gira a sinistra e muoviti un passo in avanti
[!java|c]'I'[/!][!scala|python]"I"[/!] | Girati indietro e muoviti un passo in avanti
[!java|c]'A'[/!][!scala|python]"A"[/!] | Muoviti un passo avanti
[!java|c]'B'[/!][!scala|python]"B"[/!] | Muoviti due passi in avanti
[!java|c]'C'[/!][!scala|python]"C"[/!] | Muoviti tre passi in avanti
[!java|c]'D'[/!][!scala|python]"D"[/!] | Muoviti quattro passi in avanti
[!java|c]'E'[/!][!scala|python]"E"[/!] | Muoviti cinque passi in avanti
[!java|c]'F'[/!][!scala|python]"F"[/!] | Muoviti sei passi in avanti
[!java|c]'Z'[/!][!scala|python]"Z"[/!] | Muoviti un passo indietro
[!java|c]'Y'[/!][!scala|python]"Y"[/!] | Muoviti due passi indietro
[!java|c]'X'[/!][!scala|python]"X"[/!] | Muoviti tre passi indietro
[!java|c]'W'[/!][!scala|python]"W"[/!] | Muoviti quattro passi indietro
[!java|c]'V'[/!][!scala|python]"V"[/!] | Muoviti cinque passi indietro
[!java|c]'U'[/!][!scala|python]"U"[/!] | Muoviti sei passi indietro
(qualsiasi altra cosa) | Fine delle danze

Quan il tuo programma funzionerà di nuovo, procedi con il prossimo esercizio.