Categories
Tech

F# Friday – The List.append Function

Occasionally, you need to combine two lists (or arrays or sequences) into one. List.append to the rescue! (Along with Array.append and Seq.append.)

A widow Carol has three daughters: Marcia, Jan, and Cindy.

let ladies = ["Carol"; "Marcia"; "Jan"; "Cindy"]

A widower Mike has three sons: Greg, Peter, and Bobby.

let fellas = ["Mike"; "Greg"; "Peter"; "Bobby"]

That lovely lady meets that fellow, and they know it is much more than a hunch. They marry and form a family:

let bunch = List.append ladies fellas
// val bunch : string list =
//   ["Carol"; "Marcia"; "Jan"; "Cindy";
//    "Mike"; "Greg"; "Peter"; "Bobby"]

Of course, as you probably have guessed, order matters. Let’s reverse the arguments:

let bunch2 = List.append fellas ladies
// val bunch2 : string list =
//   ["Mike"; "Greg"; "Peter"; "Bobby";
//    "Carol"; "Marcia"; "Jan"; "Cindy"]

A note of caution: Idiomatic F# takes heavy advantage of the forward pipeline operator (|>). It may be tempting to do this, but watch out:

let yikes = [1; 2]
            |> List.append [3; 4]
// val yikes : int list = [3; 4; 1; 2]

Probably not what you wanted. This is one of those situations when the backward pipeline operator (<|) can step in to help you preserve readability:

let inOrder = [1; 2]
              |> List.append <| [3; 4]
// val inOrder : int list = [1; 2; 3; 4]

And you can even continue fluidly applying additional operations:

let inOrderAndTrebled = [1; 2]
                        |> List.append <| [3; 4]
                        |> List.map ((*) 3)
// val inOrderAndTrebled : int list = [3; 6; 9; 12]

Update: Thanks to Isaac Abraham for reminding me that there is a list concatenation operator (@), so this works and is nicely readable, too:

let concatenated = [1; 2] @ [3; 4]
// val concatenated : int list = [1; 2; 3; 4]

Note that @ works for lists only, not sequences or arrays.

3 replies on “F# Friday – The List.append Function”

Nice post. A couple of enhancements that might be useful: –

1. You don’t need the backpipe for the List.append e.g. List.append [3;4] works fine – it’s only needed when () are involved.
2. You can also use the shortcut append @ operator e.g. [1;2] @ [3;4].

Cheers :-)

@Isaac, thanks for the note.

  1. My point about the backward pipeline operator is that if you want to take [1;2] and [3;4] and put them together to get [1;2;3;4], then the following does not give you that result:

    [1;2] |> List.append [3;4] // yields [3;4;1;2]

    If you want to preserve reading order (for us westerners who typically read left-to-right), then the backward pipeline operator can do that:

    [1;2] |> List.append < | [3;4] // yields [1;2;3;4]

  2. Ah, yes, great point! I forgot all about it. I’ll update the post with a quick note about it.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.