F # 10: Lists

Any serious programming in any language will always include lists. Thus, you will be pleased to know that F # supports lists very, very well with its List module. A list in F # is an ordered, unchanging series of elements of the same type.

Create a list


There are several ways in F # that you can 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 

image

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 ] 

image

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 

image

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 

image

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)) 

image

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] 

image

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:

image

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]) 

image

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) 

image

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" 

image

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.

image

So, let's see the results of the example shown a little higher with the following list [1; 2; 3; four; 5]

image

You can see that everything works just fine, and it stops working when the value matches an empty list, as expected.

Source: https://habr.com/ru/post/471998/


All Articles