Tom Wayne
Tom Wayne

Reputation: 57

Confused with Swift Where Clause.

So i'm still learning but i'm struggling to understand a certain part of this code:

  case let newSquare where newSquare > finalSquare:
    // diceRoll will move us beyond the final square, so roll again
    continue gameLoop

Why does newSquare end up being 27, 28 and 29 each time I run through the loop?

Shouldn't newSquare be 0 each time? I've tried printing out newSquare in the loop and each time it turns out to be 27, 28, 29.

Here is the full code for reference:

let finalSquare = 25
var board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

gameLoop: while square != finalSquare {
    if ++diceRoll == 7 { diceRoll = 1 }
    switch square + diceRoll {
    case finalSquare:
        // diceRoll will move us to the final square, so the game is over
        break gameLoop

    case let newSquare where newSquare > finalSquare:
        // diceRoll will move us beyond the final square, so roll again
        continue gameLoop

    default:
        // this is a valid move, so find out its effect
        square += diceRoll
        square += board[square]
    }
}
print("Game over!")

Sorry i'm sure it's simple but I'm not quite getting it :/

Upvotes: 1

Views: 488

Answers (2)

0x416e746f6e
0x416e746f6e

Reputation: 10136

The construct is actually not just mere:

case let newSquare where newSquare > finalSquare: // ...

... but:

switch square + diceRoll {
// ...
case let newSquare where newSquare > finalSquare: // ...

switch statement evaluates (square + diceRoll) and compares it to all specified cases in the order. First one to be true wins and assumes the control of execution.

In this particular example, case let newSquare where newSquare > finalSquare will "win" every time when (square + diceRoll) > finalSquare, which in terms of the game-logic means that we run over the board limit. In-place constant newSquare is of no real use here (i.e. we do not use its value anyhow) and is introduced just to be able to use where statement of switch-case.

Temporary constant newSquare gets initialised via so called value binding:

A switch case can bind the value or values it matches to temporary constants, for use in the body of the case. This is known as value binding, because the values are “bound” to temporary constants within the case’s body.


BTW, alternative way of saying almost the same thing as in the example would be:

switch square + diceRoll {
// ...
case finalSquare..<Int.max: // ...

... as preceding case finalSquare will take care of the option that we end up precisely on the final square, while range finalSquare..<Int.max will get to be evaluated only afterwards, therefore will only trigger if (square + diceRoll) is greater than finalSquare.

Upvotes: 1

Jacob Gorban
Jacob Gorban

Reputation: 1461

It's because newSquare becomes the value (because of let) of square + diceRoll when (where) the condition newSquare > finalSquare is true.

Since finalSquare is 25, then only when square + diceRoll will be over 25, this case will execute.

Upvotes: 1

Related Questions