12 Days of Christmas with F#

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
6
down vote

favorite
1












I've implemented 12 Days of Christmas just by using pattern matching. It's not very efficient as it performs 12 iterations, each performing its own iteration (potentially from 12 down to 1... does tail recursion kick in here though?) but I supposed I can live with that at the moment. I'm more concerned with learning how idiomatic F# is written. Would an F# programmer be more concerned with creating types, etc.?



module Christmas
let getOrdinal num =
match num with
| 1 -> sprintf "%ist" num
| 2 -> sprintf "%ind" num
| 3 -> sprintf "%ird" num
| _ -> sprintf "%ith" num

let getPreamble num =
sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)

let rec getVerse verse num =
match num with
| 12 -> getVerse (List.append verse ["12 drummers drumming"]) (num - 1)
| 11 -> getVerse (List.append verse ["11 pipers piping"]) (num - 1)
| 10 -> getVerse (List.append verse ["10 lords a-leaping"]) (num - 1)
| 9 -> getVerse (List.append verse ["9 ladies dancing"]) (num - 1)
| 8 -> getVerse (List.append verse ["8 maids a-milking"]) (num - 1)
| 7 -> getVerse (List.append verse ["7 swans a-swimming"]) (num - 1)
| 6 -> getVerse (List.append verse ["6 geese a-laying"]) (num - 1)
| 5 -> getVerse (List.append verse ["5 golden rings"]) (num - 1)
| 4 -> getVerse (List.append verse ["4 calling birds"]) (num - 1)
| 3 -> getVerse (List.append verse ["3 French hens"]) (num - 1)
| 2 -> getVerse (List.append verse ["2 turtle doves, and"]) (num - 1)
| _ -> List.append verse ["A partridge in a pear tree"]

let composeVerse num =
List.append [getPreamble num] (getVerse num)
|> List.fold (fun r s -> r + s + "n") ""


[1 .. 12]
|> Seq.iter (fun a -> printfn "%s" (composeVerse a))






share|improve this question



























    up vote
    6
    down vote

    favorite
    1












    I've implemented 12 Days of Christmas just by using pattern matching. It's not very efficient as it performs 12 iterations, each performing its own iteration (potentially from 12 down to 1... does tail recursion kick in here though?) but I supposed I can live with that at the moment. I'm more concerned with learning how idiomatic F# is written. Would an F# programmer be more concerned with creating types, etc.?



    module Christmas
    let getOrdinal num =
    match num with
    | 1 -> sprintf "%ist" num
    | 2 -> sprintf "%ind" num
    | 3 -> sprintf "%ird" num
    | _ -> sprintf "%ith" num

    let getPreamble num =
    sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)

    let rec getVerse verse num =
    match num with
    | 12 -> getVerse (List.append verse ["12 drummers drumming"]) (num - 1)
    | 11 -> getVerse (List.append verse ["11 pipers piping"]) (num - 1)
    | 10 -> getVerse (List.append verse ["10 lords a-leaping"]) (num - 1)
    | 9 -> getVerse (List.append verse ["9 ladies dancing"]) (num - 1)
    | 8 -> getVerse (List.append verse ["8 maids a-milking"]) (num - 1)
    | 7 -> getVerse (List.append verse ["7 swans a-swimming"]) (num - 1)
    | 6 -> getVerse (List.append verse ["6 geese a-laying"]) (num - 1)
    | 5 -> getVerse (List.append verse ["5 golden rings"]) (num - 1)
    | 4 -> getVerse (List.append verse ["4 calling birds"]) (num - 1)
    | 3 -> getVerse (List.append verse ["3 French hens"]) (num - 1)
    | 2 -> getVerse (List.append verse ["2 turtle doves, and"]) (num - 1)
    | _ -> List.append verse ["A partridge in a pear tree"]

    let composeVerse num =
    List.append [getPreamble num] (getVerse num)
    |> List.fold (fun r s -> r + s + "n") ""


    [1 .. 12]
    |> Seq.iter (fun a -> printfn "%s" (composeVerse a))






    share|improve this question























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      I've implemented 12 Days of Christmas just by using pattern matching. It's not very efficient as it performs 12 iterations, each performing its own iteration (potentially from 12 down to 1... does tail recursion kick in here though?) but I supposed I can live with that at the moment. I'm more concerned with learning how idiomatic F# is written. Would an F# programmer be more concerned with creating types, etc.?



      module Christmas
      let getOrdinal num =
      match num with
      | 1 -> sprintf "%ist" num
      | 2 -> sprintf "%ind" num
      | 3 -> sprintf "%ird" num
      | _ -> sprintf "%ith" num

      let getPreamble num =
      sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)

      let rec getVerse verse num =
      match num with
      | 12 -> getVerse (List.append verse ["12 drummers drumming"]) (num - 1)
      | 11 -> getVerse (List.append verse ["11 pipers piping"]) (num - 1)
      | 10 -> getVerse (List.append verse ["10 lords a-leaping"]) (num - 1)
      | 9 -> getVerse (List.append verse ["9 ladies dancing"]) (num - 1)
      | 8 -> getVerse (List.append verse ["8 maids a-milking"]) (num - 1)
      | 7 -> getVerse (List.append verse ["7 swans a-swimming"]) (num - 1)
      | 6 -> getVerse (List.append verse ["6 geese a-laying"]) (num - 1)
      | 5 -> getVerse (List.append verse ["5 golden rings"]) (num - 1)
      | 4 -> getVerse (List.append verse ["4 calling birds"]) (num - 1)
      | 3 -> getVerse (List.append verse ["3 French hens"]) (num - 1)
      | 2 -> getVerse (List.append verse ["2 turtle doves, and"]) (num - 1)
      | _ -> List.append verse ["A partridge in a pear tree"]

      let composeVerse num =
      List.append [getPreamble num] (getVerse num)
      |> List.fold (fun r s -> r + s + "n") ""


      [1 .. 12]
      |> Seq.iter (fun a -> printfn "%s" (composeVerse a))






      share|improve this question













      I've implemented 12 Days of Christmas just by using pattern matching. It's not very efficient as it performs 12 iterations, each performing its own iteration (potentially from 12 down to 1... does tail recursion kick in here though?) but I supposed I can live with that at the moment. I'm more concerned with learning how idiomatic F# is written. Would an F# programmer be more concerned with creating types, etc.?



      module Christmas
      let getOrdinal num =
      match num with
      | 1 -> sprintf "%ist" num
      | 2 -> sprintf "%ind" num
      | 3 -> sprintf "%ird" num
      | _ -> sprintf "%ith" num

      let getPreamble num =
      sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)

      let rec getVerse verse num =
      match num with
      | 12 -> getVerse (List.append verse ["12 drummers drumming"]) (num - 1)
      | 11 -> getVerse (List.append verse ["11 pipers piping"]) (num - 1)
      | 10 -> getVerse (List.append verse ["10 lords a-leaping"]) (num - 1)
      | 9 -> getVerse (List.append verse ["9 ladies dancing"]) (num - 1)
      | 8 -> getVerse (List.append verse ["8 maids a-milking"]) (num - 1)
      | 7 -> getVerse (List.append verse ["7 swans a-swimming"]) (num - 1)
      | 6 -> getVerse (List.append verse ["6 geese a-laying"]) (num - 1)
      | 5 -> getVerse (List.append verse ["5 golden rings"]) (num - 1)
      | 4 -> getVerse (List.append verse ["4 calling birds"]) (num - 1)
      | 3 -> getVerse (List.append verse ["3 French hens"]) (num - 1)
      | 2 -> getVerse (List.append verse ["2 turtle doves, and"]) (num - 1)
      | _ -> List.append verse ["A partridge in a pear tree"]

      let composeVerse num =
      List.append [getPreamble num] (getVerse num)
      |> List.fold (fun r s -> r + s + "n") ""


      [1 .. 12]
      |> Seq.iter (fun a -> printfn "%s" (composeVerse a))








      share|improve this question












      share|improve this question




      share|improve this question








      edited Mar 26 at 3:16









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Mar 26 at 2:59









      Jim Wharton

      1655




      1655




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          You should generally avoid List.append because appending to a singly-linked list is quite inefficient.



          I think your getVerse function is probably doing too much. You can have a function to get a line at a time which is just int -> string



          Recursion can be avoided here if you switch to a list comprehension (the for...in syntax). Recursion is rarely needed in F#.



          Even folding can be avoided here as it's simpler to use String.concat.



          With all of these changes and a couple more:



          let ordinalSuffix = function 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th"

          let preamble num =
          sprintf "On the %i%s day of Christmas, my true love gave to me" num (ordinalSuffix num)

          let line num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let verse num =
          preamble num :: [ for i in num .. -1 .. 1 -> line i ]
          |> String.concat "n"

          [1 .. 12] |> List.map verse |> String.concat "nn" |> printfn "%s"





          share|improve this answer























          • Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
            – Jim Wharton
            Mar 26 at 15:16

















          up vote
          2
          down vote













          I think TheQuickBownFox's suggestion is rather elegant. With a little twist (the use of List.mapFold) it is only necessary to call line num once per num:



          module Christmas =

          let getOrdinal num =
          match num with
          | 1 -> sprintf "%ist" num
          | 2 -> sprintf "%ind" num
          | 3 -> sprintf "%ird" num
          | _ -> sprintf "%ith" num

          let getPreamble num =
          sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)


          let getVerseLine num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let composeVerse num verseLines =
          let verse = (getVerseLine num)::verseLines
          (getPreamble num)::verse, verse

          let getVerses=
          fst ([1 .. 12] |> List.mapFold (fun verseLines num -> composeVerse num verseLines) )





          share|improve this answer

















          • 1




            mapFold That's actually a new one for me. Super cool suggestion.
            – Jim Wharton
            Mar 26 at 15:16










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f190467%2f12-days-of-christmas-with-f%23new-answer', 'question_page');

          );

          Post as a guest






























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          3
          down vote



          accepted










          You should generally avoid List.append because appending to a singly-linked list is quite inefficient.



          I think your getVerse function is probably doing too much. You can have a function to get a line at a time which is just int -> string



          Recursion can be avoided here if you switch to a list comprehension (the for...in syntax). Recursion is rarely needed in F#.



          Even folding can be avoided here as it's simpler to use String.concat.



          With all of these changes and a couple more:



          let ordinalSuffix = function 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th"

          let preamble num =
          sprintf "On the %i%s day of Christmas, my true love gave to me" num (ordinalSuffix num)

          let line num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let verse num =
          preamble num :: [ for i in num .. -1 .. 1 -> line i ]
          |> String.concat "n"

          [1 .. 12] |> List.map verse |> String.concat "nn" |> printfn "%s"





          share|improve this answer























          • Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
            – Jim Wharton
            Mar 26 at 15:16














          up vote
          3
          down vote



          accepted










          You should generally avoid List.append because appending to a singly-linked list is quite inefficient.



          I think your getVerse function is probably doing too much. You can have a function to get a line at a time which is just int -> string



          Recursion can be avoided here if you switch to a list comprehension (the for...in syntax). Recursion is rarely needed in F#.



          Even folding can be avoided here as it's simpler to use String.concat.



          With all of these changes and a couple more:



          let ordinalSuffix = function 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th"

          let preamble num =
          sprintf "On the %i%s day of Christmas, my true love gave to me" num (ordinalSuffix num)

          let line num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let verse num =
          preamble num :: [ for i in num .. -1 .. 1 -> line i ]
          |> String.concat "n"

          [1 .. 12] |> List.map verse |> String.concat "nn" |> printfn "%s"





          share|improve this answer























          • Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
            – Jim Wharton
            Mar 26 at 15:16












          up vote
          3
          down vote



          accepted







          up vote
          3
          down vote



          accepted






          You should generally avoid List.append because appending to a singly-linked list is quite inefficient.



          I think your getVerse function is probably doing too much. You can have a function to get a line at a time which is just int -> string



          Recursion can be avoided here if you switch to a list comprehension (the for...in syntax). Recursion is rarely needed in F#.



          Even folding can be avoided here as it's simpler to use String.concat.



          With all of these changes and a couple more:



          let ordinalSuffix = function 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th"

          let preamble num =
          sprintf "On the %i%s day of Christmas, my true love gave to me" num (ordinalSuffix num)

          let line num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let verse num =
          preamble num :: [ for i in num .. -1 .. 1 -> line i ]
          |> String.concat "n"

          [1 .. 12] |> List.map verse |> String.concat "nn" |> printfn "%s"





          share|improve this answer















          You should generally avoid List.append because appending to a singly-linked list is quite inefficient.



          I think your getVerse function is probably doing too much. You can have a function to get a line at a time which is just int -> string



          Recursion can be avoided here if you switch to a list comprehension (the for...in syntax). Recursion is rarely needed in F#.



          Even folding can be avoided here as it's simpler to use String.concat.



          With all of these changes and a couple more:



          let ordinalSuffix = function 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th"

          let preamble num =
          sprintf "On the %i%s day of Christmas, my true love gave to me" num (ordinalSuffix num)

          let line num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let verse num =
          preamble num :: [ for i in num .. -1 .. 1 -> line i ]
          |> String.concat "n"

          [1 .. 12] |> List.map verse |> String.concat "nn" |> printfn "%s"






          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Mar 26 at 15:19


























          answered Mar 26 at 12:36









          TheQuickBrownFox

          38116




          38116











          • Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
            – Jim Wharton
            Mar 26 at 15:16
















          • Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
            – Jim Wharton
            Mar 26 at 15:16















          Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
          – Jim Wharton
          Mar 26 at 15:16




          Great point on appending to a singly-linked list. I was completely unaware that F# devs avoid recursion. Thank you for reminding me of the cons operator in the verse function. Great feedback! Thank you!
          – Jim Wharton
          Mar 26 at 15:16












          up vote
          2
          down vote













          I think TheQuickBownFox's suggestion is rather elegant. With a little twist (the use of List.mapFold) it is only necessary to call line num once per num:



          module Christmas =

          let getOrdinal num =
          match num with
          | 1 -> sprintf "%ist" num
          | 2 -> sprintf "%ind" num
          | 3 -> sprintf "%ird" num
          | _ -> sprintf "%ith" num

          let getPreamble num =
          sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)


          let getVerseLine num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let composeVerse num verseLines =
          let verse = (getVerseLine num)::verseLines
          (getPreamble num)::verse, verse

          let getVerses=
          fst ([1 .. 12] |> List.mapFold (fun verseLines num -> composeVerse num verseLines) )





          share|improve this answer

















          • 1




            mapFold That's actually a new one for me. Super cool suggestion.
            – Jim Wharton
            Mar 26 at 15:16














          up vote
          2
          down vote













          I think TheQuickBownFox's suggestion is rather elegant. With a little twist (the use of List.mapFold) it is only necessary to call line num once per num:



          module Christmas =

          let getOrdinal num =
          match num with
          | 1 -> sprintf "%ist" num
          | 2 -> sprintf "%ind" num
          | 3 -> sprintf "%ird" num
          | _ -> sprintf "%ith" num

          let getPreamble num =
          sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)


          let getVerseLine num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let composeVerse num verseLines =
          let verse = (getVerseLine num)::verseLines
          (getPreamble num)::verse, verse

          let getVerses=
          fst ([1 .. 12] |> List.mapFold (fun verseLines num -> composeVerse num verseLines) )





          share|improve this answer

















          • 1




            mapFold That's actually a new one for me. Super cool suggestion.
            – Jim Wharton
            Mar 26 at 15:16












          up vote
          2
          down vote










          up vote
          2
          down vote









          I think TheQuickBownFox's suggestion is rather elegant. With a little twist (the use of List.mapFold) it is only necessary to call line num once per num:



          module Christmas =

          let getOrdinal num =
          match num with
          | 1 -> sprintf "%ist" num
          | 2 -> sprintf "%ind" num
          | 3 -> sprintf "%ird" num
          | _ -> sprintf "%ith" num

          let getPreamble num =
          sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)


          let getVerseLine num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let composeVerse num verseLines =
          let verse = (getVerseLine num)::verseLines
          (getPreamble num)::verse, verse

          let getVerses=
          fst ([1 .. 12] |> List.mapFold (fun verseLines num -> composeVerse num verseLines) )





          share|improve this answer













          I think TheQuickBownFox's suggestion is rather elegant. With a little twist (the use of List.mapFold) it is only necessary to call line num once per num:



          module Christmas =

          let getOrdinal num =
          match num with
          | 1 -> sprintf "%ist" num
          | 2 -> sprintf "%ind" num
          | 3 -> sprintf "%ird" num
          | _ -> sprintf "%ith" num

          let getPreamble num =
          sprintf "On the %s day of Christmas, my true love gave to me" (getOrdinal num)


          let getVerseLine num =
          match num with
          | 12 -> "12 drummers drumming"
          | 11 -> "11 pipers piping"
          | 10 -> "10 lords a-leaping"
          | 9 -> "9 ladies dancing"
          | 8 -> "8 maids a-milking"
          | 7 -> "7 swans a-swimming"
          | 6 -> "6 geese a-laying"
          | 5 -> "5 golden rings"
          | 4 -> "4 calling birds"
          | 3 -> "3 French hens"
          | 2 -> "2 turtle doves, and"
          | _ -> "A partridge in a pear tree"

          let composeVerse num verseLines =
          let verse = (getVerseLine num)::verseLines
          (getPreamble num)::verse, verse

          let getVerses=
          fst ([1 .. 12] |> List.mapFold (fun verseLines num -> composeVerse num verseLines) )






          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered Mar 26 at 13:36









          Henrik Hansen

          3,8931417




          3,8931417







          • 1




            mapFold That's actually a new one for me. Super cool suggestion.
            – Jim Wharton
            Mar 26 at 15:16












          • 1




            mapFold That's actually a new one for me. Super cool suggestion.
            – Jim Wharton
            Mar 26 at 15:16







          1




          1




          mapFold That's actually a new one for me. Super cool suggestion.
          – Jim Wharton
          Mar 26 at 15:16




          mapFold That's actually a new one for me. Super cool suggestion.
          – Jim Wharton
          Mar 26 at 15:16












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f190467%2f12-days-of-christmas-with-f%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods