I've always thought that appending a list to another one meant copying the objects from the first list and then pointing to the appended list as described for example here. However, in this blog post and in its comment, it says that it is only the pointers that are copied and not the underlying objects. So what is correct?
3 Answers
Drawing from Snowbear's answer, a more accurate image of combining two lists (than the one presented in the first referred article in the question) would be as shown below.
let FIRST = [1;2;3]
let SECOND = [4;5;6]
let COMBINED = FIRST @ SECOND

- 7,433
- 4
- 36
- 61
-
7This is basically correct but, just to confuse things, this is correct for 1, 2 and 3 denoting values of reference types. If they are value types (e.g. `int`) then they do actually get copied. – J D Aug 19 '12 at 21:40
In the functional world, lists are immutable. This means that node sharing is possible because the original lists will never change. Because the first list ends with the empty list, its nodes must be copied in order to point its last node to the second list.
If you mean this statement then the answer is seems to be pretty simple. Author of the first article is talking about list node elements when he says nodes
. Node element is not the same as the list item itself. Take a look at the pictures in the first article. There are arrows going from every element to the next node. These arrows are pointers. But integer type (which is put into the list) has no such pointers. There is probably some list node
type which wraps those integers and stores the pointers. When author says that nodes must be copies
he is talking about these wrappers being copied. The underlying objects (if they were not value types as in this case) would not be cloned, new wrappers will point to the same object as before.

- 16,924
- 3
- 43
- 67
-
1Then the image in the first article showing the first, second and the combined lists is somewhat misleading since you get the impression that the underlying objects have also been copied (the values 1, 2 and 3). I guess a more accurate image would be the one posted below. – Christian Aug 19 '12 at 19:21
-
@Christian, yes, that image is closer to the real world than the one from the article. I think you should mark your answer as accepted since your image worth thousand of words. – Snowbear Aug 19 '12 at 19:53
F# lists hold references (not to be confused with F#'s ref
) to their elements; list operations copy those references (pointers), but not the elements themselves.
There are two ways you might append items to an existing list, which is why there seems to be a discrepancy between the articles (though they both look to be correct):
- Cons operator (
::
): The cons operator prepends a single item to an F# list, producing a new list. It's very fast (O(1)
), since it only needs to call a very simple constructor to produce the new list. - Append operator (
@
): The append operator appends two F# lists together, producing a new list. It's not as fast (O(n)
) because in order for the elements of the combined list to be ordered correctly, it needs to traverse the entire list on the left-hand-side of the operator (so copying can start at the first element of that list). You'll still see this used in production if the list on the left-hand-side is known to be very small, but in general you'll get much better performance from using::
.

- 104,111
- 38
- 209
- 254

- 11,487
- 1
- 29
- 34