Buggle Dance Revolution 2 (BDR2)

[!java|scala|c]

BDR is cool, but it's a bit chaotic. First, the buggles giggle in any directions, and then the code you had to write to let them move is rather difficult to read. Here is a new BDR world where the buggle will dance a gentle circle. We will benefit this tranquillity to clean up a bit our code thanks to the new constructs we will introduce.

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

The hardest part of previous code is certainly the conditional cascading. Somewhere in your code, you certainly had something similar to:

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 (expression) {
  case firstValue: 
    whatToDoIfExpressionEqualsFirstValue();
    break;
  case secondValue: 
    whatToDoIfExpressionEqualsSecondValue();
    break;
  case thirdValue: 
    whatToDoIfExpressionEqualsThirdValue();
    break;
    /* as much similar cases as you want */
  default: 
    whatToDoIfExpressionDoesNotEqualsAnySeenValues();
}

Observe that each branch of a switch must be ended by a break. If you forget this, the machine keeps going and execute the next branch in the list after the branch it jumped to. There is even some rare cases where this behavior reveals helpful.

It is then possible to rewrite previous BDR code in a cleaner way using the switch construct:

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]
expression match {
  case possible value => instructions
  case other value     => other instructions
  case another value => yet another instructions
  case _                 => default instructions
}

The expression provided before the keyword match, and then the branches are evaluated one after the other until we find one which value provided between case and => is equal to the expression's value. The _ symbol acts as a wildcard, so the _ branch always matches. Here is an example where a variable name is matched.

name match {
  case "Martin" => println("Hello Martin, how are you?")
  case "Gerald" => println("Hey Gerald! How are you doing?")
  case _            => println("Welcome stranger.")
}

It is possible to have more than one instruction per branch, and merge branches when the values are separated by a | symbol.

name match {
  case "Martin" | "Gerald" => println("Hello "+name+", how are you?"); openTheDoor()
  case _                            => println("Hello stranger. Please do not pass."); 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("Hey kid!")
  case i if i<20 => println("Hey dude!")
  case i if i<30 => println("Hello young man")
  case _           => println("Hello Sir")
}

Note that there is no need to check whether the value is higher than 10 on the second line because the first matching branch is used. So, if the second branch gets evaluated, then the first one did not match.

Finally, it is possible also to match several variables in one shoot!

(x,y) match {
 case (0,0) => println("that's the origin")
 case (_,0) => println("On the ordinate")
 case (0,_) => println("On the abscissa")
 case (_,_) => println("Some random point")
}

I told you that scala's pattern matching is very powerful! I actually love this feature!

[/!]

Exercise goal

[!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.

Повідомлення Що робити
[!java|c]'R'[/!][!scala|python]"R"[/!]Повернути праворуч і зробити один крок вперед
[!java|c]'L'[/!][!scala|python]"L"[/!]Turn left and move one step forward
[!java|c]'I'[/!][!scala|python]"I"[/!]Turn back and move one step forward
[!java|c]'A'[/!][!scala|python]"A"[/!]Move one step forward
[!java|c]'B'[/!][!scala|python]"B"[/!]Move two steps forward
[!java|c]'C'[/!][!scala|python]"C"[/!]Move three steps forward
[!java|c]'D'[/!][!scala|python]"D"[/!]Move four cells forward
[!java|c]'E'[/!][!scala|python]"E"[/!]Move five cells forward
[!java|c]'F'[/!][!scala|python]"F"[/!]Move six cells forward
[!java|c]'Z'[/!][!scala|python]"Z"[/!]Move one step backward
[!java|c]'Y'[/!][!scala|python]"Y"[/!]Move two steps backward
[!java|c]'X'[/!][!scala|python]"X"[/!]Move three steps backward
[!java|c]'W'[/!][!scala|python]"W"[/!]Move four cells backward
[!java|c]'V'[/!][!scala|python]"V"[/!]Move five cells backward
[!java|c]'U'[/!][!scala|python]"U"[/!]Move six cells backward
(усе інше)Stop dancing.

When you program works again, proceed to next exercise.