A
matchstatement is a very clean way of dealing with a set of possible inputs that need to be treated in different ways. It also helps reduce the number of bugs because the compiler will complain if we haven’t specified a scenario for every possible value of the input.
When picking up a card we used an if statement to test if the deck was empty. We could instead use a much more readable match statement.
// ORIGINAL
let pickupCard (hand: Card list) (deck: Card list) =
if deck.Length = 0 then
failwith "No cards left!!"
else
let topcard = deck[0]
hand @ [topcard]
// WITH ~~ MATCH ~~
let pickupCard (hand: Card list) (deck: Card list) =
match deck with
| [] -> failwith "No cards left!!!"
| [a] -> hand @ [a]
| a::rest -> hand @ [a]
Line by line in the pickupCard function:
match on the deck value.TIP: the compiler takes the first matching test from top to bottom. Something you need to be mindful of if you have two tests that could both possibly be true.
The most useful “special” operator that I use in F# is the pipe operator |>
The pipe operator takes whatever is on the left and “pipes” it into the function on the right as the last parameter value. i.e
b |> func ais the same asfunc a bWhat this allows us to do is chain functions together to create a bigger composite function.
let add a b = a + b let multiply a b = a * b let chained = 7 // 7 |> add 4 // 11 |> mutiply 6 // 66 |> add 2 // 68
With this knowledge we can slightly improve our newDeck calculation to
let newDeck =
let suits = [Hearts; Diamonds; Clubs; Spades]
let numbers = [
Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
Jack; Queen; King; Ace
]
List.allPairs suits numbers
|> List.map (fun (suit, number) -> suit number)
type CardNumber =
| Two
| Three
| Four
| Five
| Six
| Seven
| Eight
| Nine
| Ten
| Jack
| Queen
| King
| Ace
type Card =
| Hearts of CardNumber
| Diamonds of CardNumber
| Clubs of CardNumber
| Spades of CardNumber
| Joker
let hand = [Hearts Three; Diamonds Ten; Clubs King; Joker]
let newDeck =
let suits = [Hearts; Diamonds; Clubs; Spades]
let numbers = [
Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
Jack; Queen; King; Ace
]
List.allPairs suits numbers
|> List.map (fun (suit, number) -> suit number)
let pickupCard (hand: Card list) (deck: Card list) =
match deck with
| [] -> failwith "No cards left!!!"
| [a] -> hand @ [a]
| a::rest -> hand @ [a]
;;
// DO IT!
pickupCard hand newDeck