Create a list
There are several ways in F # that you can create a list.
- Create an empty list
- Create a simple list with items from 1 to 10
- Create a list with odd numbers in the range from 1 to 10
- Use the for loop to create a list.
let prettyPrint desc list = printfn desc printfn "%A" list //empty list let listEmpty = [] //simple list let list1 = [1 .. 10 ] //simple list, with step value let list2 = [1 ..2..10 ] //using for loops to create lists let list3 = [for i in 1 .. 10 -> i*2 ] prettyPrint "let listEmpty = []" listEmpty prettyPrint "let list1 = [ 1 .. 10 ]" list1 prettyPrint "let list2 = [ 1 .. 2..10 ]" list2 prettyPrint "[ for i in 1 .. 10 -> i*2 ]" list3
The last example shown above shows how to use the for loop to create a list, which is very cool, but there is something even more cool and powerful in the F # toolkit, namely List Comprehensions.
List Comprehensions is a powerful method that allows you to create lists using pretty much the standard F #, which includes functions / loops / conditions, etc.
Let's continue to look at an example of how we could create lists.
let is2 x = match x with | 2 -> "YES" | _ -> "NO" //yield directly let list1 = [ yield 1; yield 2; yield 3; ] //yield numbers between 1 and 20 where we use the //Math.Pow function to return a new number let list2 = [for i in 1.0 .. 20.0 do yield Math.Pow(i,2.0) ] //yield only numbers between 1 and 20 that //can be divided by 5 let list3 = [ for i in 1 .. 20 do if i % 5 = 0 then yield i ] //yields YES/NO strings depending on //whether source int = 2 or not let list4 = [for i in 1 .. 5 -> is2 i ]
Some useful list operators
Cons operator
We can use the cons operator “::” to add values to an existing list, so suppose we had this list:
let list1 = [1;2;3;4] let list2 = 42 :: list1
Concatenation operator
Another very useful operator is the "@" operator, which allows you to combine lists of the same type. So, for example, if we had this:
let list1 = [1;2;3;4] let list2 = [5;6;7;8] let list3 = list1 @ list2
List Module
I don’t think I overdo it when I say that the List module is a key module in F #. In fact, the MSDN documentation for it is very good compared to others in F #. Therefore, I don’t think I can add a lot of usefulness to the examples found on MSDN, but I will give here a few for your convenience, but you should study MSDN for more information .
The properties
Head
'T
First element
Empty
'T list
Returns an empty list of the specified type
Isempty
bool
true - if there are no elements in the list
Item
'T
An item that is at a specific index
Length
int
Amount of elements
Tail
'T list
List without first item:
let list1 = [ 1; 2; 3 ] // Properties printfn "list1.IsEmpty is %b" (list1.IsEmpty) printfn "list1.Length is %d" (list1.Length) printfn "list1.Head is %d" (list1.Head) printfn "list1.Tail.Head is %d" (list1.Tail.Head) printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head) printfn "list1.Item(1) is %d" (list1.Item(1))
Filter
Returns a new collection containing only the elements of the collection for which the given predicate returns true. Here is a trivial example that selects only even numbers from a list to create a new list
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]
Search (find)
Returns the first element for which this function returns true. In this example, since the list from 1 to 100 contains 5, 5 is the 1st number, which is divided by 5, so this is the return value:
For all (forall)
Checks if all elements in the collection satisfy a given predicate. In this example, the entire list must contain 0 in order to get a true return value.
let isAllZeroes list = List.forall (fun elem -> elem = 0.0) list printfn "%b" (isAllZeroes [0.0; 0.0]) printfn "%b" (isAllZeroes [0.0; 1.0])
Apply to all (Iteri)
Applies this function to each item in the collection. The integer passed to the function indicates the index of the element.
let data = ["Cats";"Dogs";"Mice";"Elephants"] data |> List.iteri (fun ix -> printfn "item %d: %s" ix)
Sort by (SortWith)
Sorts the specified list using this comparison function.
let list1 = [ ""; "&"; "&&"; "&&&"; ""; "|"; "||"; "|||" ] printfn "Before sorting: " list1 |> printfn "%A" //custom sorting function let sortFunction (string1:string) (string2:string) = if (string1.Length > string2.Length) then 1 else if (string1.Length printfn "After sorting:\n%A"
There are many useful functions in the list module, this is just a small part of what you can find.
A small look at recursion over lists
No discussion of lists would be complete without talking about recursion. Recursion is what the whole post will be dedicated to, but for now, let's take a look at what it takes to write a recursive function that works on a list in F #.
let printIt desc x = printfn "%A %A" desc x let rec printList list = match list with | h :: t -> printIt "head=" h printIt "tail=" t printList t | [] -> () printList [1;2;3;4;5]
Note the use of the rec keyword, which tells the F # compiler that this function will be recursive. Without this keyword, a recursive function call - you will receive a compilation error message, although with a not very clear error text.
So, let's see the results of the example shown a little higher with the following list [1; 2; 3; four; 5]
You can see that everything works just fine, and it stops working when the value matches an empty list, as expected.