Prepending to a list in F# is somewhat annoying because once you're done you have to reverse it. Is there a way to build a list straight from start?
You can attach elements to a list by using the :: (cons) operator. If list1 is [2; 3; 4] , the following code creates list2 as [100; 2; 3; 4] . You can concatenate lists that have compatible types by using the @ operator, as in the following code.
Append in Python is a pre-defined method used to add a single item to certain collection types. Without the append method, developers would have to alter the entire collection's code for adding a single value or item. Its primary use case is seen for a list collection type.
The append() method appends an element to the end of the list.
The List<'T> class represents a strongly typed list of objects that can be accessed by index. It is a mutable counterpart of the List class. It is similar to arrays, as it can be accessed by an index, however, unlike arrays, lists can be resized.
There is nothing wrong with prepending and reversing the list. You can use append (@
) on a single-element list, but it is a code smell. A tolerable (tail-recursive) approach is:
let appendSingle xs x =
[ yield! xs
yield x ]
All the above solutions have O(n) execution time. For your use case, you could keep a private ResizeArray to avoid the use of reverse. It is fine since mutability is hidden. Compare this function
let filter f l =
let rec loop acc l =
match l with
| [] -> List.rev acc
| x::xs when f x -> loop (x::acc) xs
| x::xs -> loop acc xs
loop [] l
with its more efficient counterpart
let filter f l =
let rec loop (acc : ResizeArray<_>) l =
match l with
| [] -> Seq.toList acc
| x::xs when f x ->
acc.Add(x)
loop acc xs
| x::xs -> loop acc xs
loop (ResizeArray()) l
If you need to append elements to the end, you can use the type known as DList
. There is an implementation available in FSharpX.
However, there is some runtime overhead associated with this (e.g. see the comments here) and so I think that building list by prepending and then reversing is generally going to be more efficient. It is also quite standard thing to do in functional programming - it may look a bit confusing at first, but it is a very common "design pattern" when implementing recursive functions that walk over lists, so I would not try to avoid it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With