I've been experimenting with the F# Bolero environment to learn F# a bit and I was trying to get the hang of pattern matching by generating ordinal numbers (1st, 2nd, 3rd, ...) from cardinal numbers (1, 2, 3, ...).
Here's the code I came up with:
let ordinal n =
if n > 20 then
match n % 10 with
| 1 -> string n + "st"
| 2 -> string n + "nd"
| 3 -> string n + "rd"
| _ -> string n + "th"
else
match n % 20 with
| 1 -> string n + "st"
| 2 -> string n + "nd"
| 3 -> string n + "rd"
| _ -> string n + "th"
let hundred = [1..100]
let hundredOrdinals = List.map ordinal hundred
printfn "First %d ordinals:\n%A" hundred.Length hundredOrdinals
Which I believe produces the right ordinal numbers both for numbers less than and numbers greater than or equal to 20.
However, the patterns that are matched are identical for both branches of the if
statement: both match an input of 1
to an output with "st"
, and input of 2
to an output with "nd"
and so on, so I was wondering if I couldn't somehow recycle the matching criteria while keeping the matching expressions (n % 20
and n % 10
). Any alternative approaches are also welcome.
Here's the output of the snippet above just in case it might contain errors, I've aligned some of the values to make it more readable.
First 100 ordinals:
[ "1st"; "2nd"; "3rd"; "4th"; "5th"; "6th"; "7th"; "8th"; "9th"; "10th";
"11th"; "12th"; "13th"; "14th"; "15th"; "16th"; "17th"; "18th"; "19th"; "20th";
"21st"; "22nd"; "23rd"; "24th"; "25th"; "26th"; "27th"; "28th"; "29th"; "30th";
"31st"; "32nd"; "33rd"; "34th"; "35th"; "36th"; "37th"; "38th"; "39th"; "40th";
"41st"; "42nd"; "43rd"; "44th"; "45th"; "46th"; "47th"; "48th"; "49th"; "50th";
"51st"; "52nd"; "53rd"; "54th"; "55th"; "56th"; "57th"; "58th"; "59th"; "60th";
"61st"; "62nd"; "63rd"; "64th"; "65th"; "66th"; "67th"; "68th"; "69th"; "70th";
"71st"; "72nd"; "73rd"; "74th"; "75th"; "76th"; "77th"; "78th"; "79th"; "80th";
"81st"; "82nd"; "83rd"; "84th"; "85th"; "86th"; "87th"; "88th"; "89th"; "90th";
"91st"; "92nd"; "93rd"; "94th"; "95th"; "96th"; "97th"; "98th"; "99th"; "100th" ]