Introduction
Programming languages provide various control structures that affect the order of code execution.
There are 3 control structures:
- Sequential control
- Selection control
- Iteration control
However, this article will focus on the area of iteration control structure, which is commonly known as loops.
That’s why in this article we’ll discuss the two types of F#’s loops: the for loop and the while loop.
Before we see the examples, code samples are written in .NET 6 and the project is a test project using Xunit.
I also recommend downloading the sample project before going through the examples.
The For Loop
The for loops have two types of expression: for ... to and for ... in.
The for...to this feature iterates over a range of values, while for...in it is more like a for each loop of C# or in other .NET languages as it loops over an enumerable collection.
The for...to Expression/Loop
The for...to expression or loop, its range can be either forward or reverse or generated via function.
Let’s see some examples.
Forward loop
[<Theory>]
[<InlineData(0, 10)>]
let ``for_to_loop_test`` (count: int, countEnd: int)=
//let's start with a simple for.. to loop
for i = count to countEnd do
let message = $"{i}"
output.WriteLine message
Assert.True( i >=0 && i <= 10)
//output 0 1 2 3 4 5 6 7 8 9 10
The example above starts from 0 and ends at 10 and as it is iterated it actually outputs the value of the variable i to the console.
Asserting whether the counter is between the range of 0 and 10.
Reverse loop
[<Theory>]
[<InlineData(10, 0)>]
let ``for_to_loop_reverse_test`` (count: int, countEnd: int) =
for counter = count downto countEnd do
let message = $"{counter}"
output.WriteLine message
Assert.True( counter >=0 && counter <= 10)
//output 10 9 8 7 6 5 4 3 2 1 0
The example above starts from 10 and ends at 0 as it iterates it actually outputs the value of the counter to the console.
Asserting whether the counter is between the range of 10 and 0.
Define the start and end values in the loop
[<Fact>]
let ``for_to_loop_with_start_and_end_function_value`` () =
let getRandomNumber startNum endNum =
let random = System.Random()
startNum * random.Next(startNum,endNum)
for counter = getRandomNumber 1 5 to getRandomNumber 5 10 do
let message = $"{counter}"
output.WriteLine(message)
Assert.True(counter >= 1 && counter<= 500)
The example above sets the start and end values from the getRandomNumber function and then randomly generates a number within its range.
Asserting whether the counter is between the range of 1 and 500.
The for...in Expression/Loop
This expression is commonly used for iterating over an enumerable collection, let's see some examples.
[<Fact>]
let ``for_in_loop_test`` () =
let companies = [|"Apple"; "Microsoft"; "Google"; "Amazon"|]
for company in companies do
let message = $"{company}"
output.WriteLine(message)
Assert.True(Array.Exists(companies, fun element -> element = message))
//output Apple Microsoft Google Amazon
The example above iterates over the companies array and outputs the name.
However, we have asserted the existence of the company name using the Array.Exists method for verification.
We can use mutable variables inside the for...in loop body, let's see an example.
[<Fact>]
let ``for_in_loop_with_mutable_variable_inside_test`` () =
let companies = [|"Apple"; "Microsoft"; "Google"; "Amazon"|]
let func_loop_with_mutable_counter =
let mutable counter = 0
for _ in companies do
let message = $"At index {counter} is {companies.[counter]}"
output.WriteLine(message)
Assert.True(not((companies |> Array.findIndex(fun element -> element = companies.[counter])) = -1))
counter <- counter + 1
//output Apple Microsoft Google Amazon
()
In the example above we have shown how we can use a mutable variable inside the for... in the code block and it is almost the same as the previous code sample.
However, the assertion is different.
In the example above we have to check whether the element (company name) is within the array using the Array.findIndex method.
The While Loop
This kind of loop is used for iteration as long as a specified condition is met.
The condition is being evaluated, and if it is true, the body will be evaluated/executed.
The evaluation/execution will continue until the condition is false.
Let's see an example.
[<Fact>]
let ``while_loop_test`` () =
let mutable isTrue = true
let mutable counter = 0
while isTrue do
if counter < 10 then
counter <- counter + 1
else
isTrue <- false
let message = $"Current counter is: {counter} and isTrue is still {isTrue}"
Assert.True(counter <= 10)
output.WriteLine(message)
()
//output
//Current counter is: 1 and isTrue is still True
//Current counter is: 2 and isTrue is still True
//Current counter is: 3 and isTrue is still True
//Current counter is: 4 and isTrue is still True
//Current counter is: 5 and isTrue is still True
//Current counter is: 6 and isTrue is still True
//Current counter is: 7 and isTrue is still True
//Current counter is: 8 and isTrue is still True
//Current counter is: 9 and isTrue is still True
//Current counter is: 10 and isTrue is still True
//Current counter is: 10 and isTrue is still False
The example above is a classic while loop example.
However, we have used mutable variables such as the isTrue and counter to show that we can use mutable variables within a block code of a while loop.
Conclusion
In this post, we have seen how we can use for and while loops using the F# language. I hope you have enjoyed this article as much as I have enjoyed writing it. Stay tuned for more.
Until next time, happy programming!