Arrays in F# - A Mutable Collection

In this article you will learn about Arrays in F#. Arrays in F# are mutable data type.

Arrays in F# are mutable data types. I started intentionally with this line, as FSharp(F#) is functional programming language and the paradigm of language promotes immutability. So, whenever there is a mutable type or value be careful with the usage. Let’s go back to main topic i.e. Arrays. In this post, we’ll see how to initialize, iterate, update and other manipulation that you can do with Arrays in FSharp(F#). In this post, we’ll cover only one dimensional array. May be we can discuss 2D, 3D, and Jagged array in advanced array post of arrays in future.

Static array initialization

In FSharp(F#), we initialize the array with the following notations:

  1. let fruits = [|"Apple""Orange""Grapes"|]  
  2. // or using every item in separate line without separator  
  3. let fruits = [|  
  4. "Apple"  
  5. "Orange"  
  6. "Grapes"  
  7. |] 
Notice additional symbol | (pipe) used with square braces to declare the array. Also the separator is no a "," comma anymore but it’s ; semicolon. Here’s an example of Array of integer sample and possible mistakes that can be done by a C# developer without getting any compile time error.
  1. let arr = [| 1; 2; 3; 4 |]  
Possible mistakes #1
  1. // most common mistakes done by developers with background of imperative language  
  2.   
  3. let arr1 = [| 1, 2, 3|]  
  4. // this is an array of tuples with one element, so no error is displayed.  
  5. // the ',' separator is used to create tuples. 
Possible mistakes #2
  1. // what if   
  2. let arr2 = [1; 2; 3]  
  3. // this is also valid but this would be a list and it's "IMMUTABLE"  
Initialization using sequence expressions
  1. // Array ofsquares of positive integers from 1 to 10  
  2. let arr3 = [| for i in 1 .. 10 -> i * i |]  
Output:

[|1; 4; 9; 16; 25; 36; 49; 64; 81; 100|]

Initialization using Array module

Array.empty

Creates a new array that does not contain any elements.
  1. // Specify the type by using a type argument.  
  2. let array1 = Array.empty<int>  
  3. // Specify the type by using a type annotation.  
  4. let array2 : int array = Array.empty  
  5.   
  6. // Even though array3 has a generic type,  
  7. // you can still use methods such as Length on it.  
  8. let array3 = Array.empty  
  9. printfn "Length of empty array: %d" array3.Length  
Output: 0

Array.create

Creates an array of a specified size and sets all the elements to provided values.
  1. // creates an array of length 10, all elements initialized with default value -1  
  2. let arrayOfTenZeroes : int array = Array.create 10 -1  
  3. // create a bool array with default value as true  
  4. let primeFlaggedArr : bool array = Array.create 10 true  
Note: In the end of this article we’ll solve the find prime number problem using Sieve of Eratosthenes.

Array.zeroCreate

Creates an array, given a dimension and a function to generate the elements.
  1. // create a bool array with default values(false)  
  2. let primeFlaggedArr : bool array = Array.zeroCreate 10  
Array.init

Creates an array, given a dimension and a function to generate the elements.
  1. // Another way to create array of squares starting from 1 to 10  
  2. printfn "Array of squares: %A" (Array.init 10 (fun index -> index * index)) 
Accessing array elements

You can access array elements by using a dot operator (.) and brackets ([ and ]).
  1. let fruits = [|  
  2. "Apple"  
  3. "Orange"  
  4. "Grapes"  
  5. |]  
  6. let firstFruit = fruits[0];
Accessing range of values from array using sliced notation,
  1. // Accesses elements from 0 to 2.  
  2. arr.[0..2]   
  3. // esses elements from the beginning of the array to 2.  
  4. arr.[..2]   
  5. // esses elements from 2 to the end of the array.  
  6. arr.[2..]   
Few more honorable mentions or generally used functions are Array.get, Array.set and Array.length which are self-explanatory.

Replacing existing value using index

Arrays are mutable so you can replace any existing value by accessing it via index and assigning a new value with ‘<-‘ operator.
  1. // Updating the value of an item in array using index  
  2. let fruits1 = [|  
  3. "Apple"  
  4. "Orange"  
  5. "Grapes"  
  6. |]  
  7.   
  8. fruits1.[0] <- "Mango"  
  9.   
  10. let print =   
  11. for (fruit) in fruits1 do  
  12. printfn "%s" fruit  
Output:

>PrintUpper [|"Apple"; "Orange"; "Grapes"|] ;;
APPLE
ORANGE
GRAPES

Iterating through array elements

Let’s create a function that takes an array of string and converts the values to upper case.
  1. let MakeUpper(arr : string array) =  
  2. for i in 0 .. arr.Length - 1 do  
  3. Array.set arr i (arr.[i].ToUpper())  
  4. printfn "%s" arr.[i]  
In visual studio select the function and run it in F# interactive.

Output:

>MakeUpper [|"Apple"; "Orange"; "Grapes"|] ;;
APPLE
ORANGE
GRAPES

With variant of for loop (foreach alike)
  1. let PrintUpper(arr : string array) =  
  2. for (fruit) in arr do  
  3. printfn "%s" (fruit.ToUpper())  
Output:

>PrintUpper [|"Apple"; "Orange"; "Grapes"|] ;;
APPLE
ORANGE
GRAPES

So now we are pretty much good to start with playing around array. Let’s try to solve few problems using array to get up to speed. As I discussed before we’ll be solving the finding prime number problem using Sieve of Eratosthenes. Here’s a function to which is based on theory given at source:
  1. // print prime number in a series up to n   
  2. let PrimeSeive(n : int) =   
  3. let sequence = [|1..n|]  
  4. let isPrime = Array.create n true  
  5. let maxSquareRoot : int = System.Convert.ToInt32(System.Math.Sqrt(float n))  
  6. let candidate = 2;  
for i in candidate..maxSquareRoot do,
  1. if isPrime.[i] then  
  2. let mutable j = i * i  
  3. while j < n - 1 do  
  4. isPrime.[j] <- false  
  5. j <- j + i  
  6.   
  7.   
  8. for index in 0..n - 1 do  
  9. if isPrime.[index] then  
  10. printf "%d, " index  
Output:

>PrimeSeive100 ;;
0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 99, val it : unit = ()

Here’s the equivalent code in CSharp(C#),
  1. public static void PrimeSeive(int n)  
  2. {  
  3.     bool[] isPrime = newbool[n + 1];  
  4.     intmaxSquareRoot = (int) Math.Sqrt(n);  
  5.   
  6.     int candidate = 2;  
  7.   
  8.     // Additional loop to initialize the bool array with default value  
  9.     for (int ind = 0; ind < isPrime.Length; ind++)  
  10.     {  
  11.         isPrime[ind] = true;  
  12.     }  
  13.   
  14.     for (inti = candidate; i < Math.Sqrt(n); i += 1)  
  15.     {  
  16.         if (isPrime[i])  
  17.             for (int j = i * i; j < n; j = j += i)  
  18.             {  
  19.                 isPrime[j] = false;  
  20.             }  
  21.     }  
  22.   
  23.     for (int k = 0; k < n; k++) {  
  24.         if (isPrime[k])  
  25.             Console.WriteLine(k);  
  26.     }  
  27. }  
Although the given solution in F# is not the best and not recommended because we’re using much of mutable types like any other imperative language. In upcoming posts, we’ll solve the same problem with immutable types and without using mutable.

Here’s few exercises for you:

What would be the output of below code?
  1. // Guess the output, Write your answer in the comments.  
  2. let guessOutput =   
  3. for i in [|9..7..30|] do  
  4. printfn "%d" i  

Read more articles on FSharp(F#):