Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / F#

F#18 : Flow Control

0.00/5 (No votes)
16 Apr 2014CPOL3 min read 15.3K  
As previously stated F# allows different styles of programming that is you can use of or all of the following: Functional Imperative OO In F# you have choices and you are free to mix and match these styles to suit your needs.

As previously stated F# allows different styles of programming that is you can use of or all of the following:

  • Functional
  • Imperative
  • OO

In F# you have choices and you are free to mix and match these styles to suit your needs. In this article we will look at flow control statements, which although quite familiar still have a certain shall we say F#ness about them.

In this article we will be looking at the following flow control statements:

  • If Then Else
  • For
  • For..To
  • While..Do

If Then Else

You would have undoubtedly used If-Then-Else flow control expressions in many other languages. What differs in F# is that If Then Else is a statement and not an expression, and as such has certain rules associated with it, such as:

  • It must produce a value, which is the value of the last expression in the tree
  • The types produced in each branch must be the same
  • If there is no explicit else branch the return type is unit, which means if the type of the then branch is anything other than unit, you will need to provide a else branch
  • You may use the elif keyword to chain If Then Else together

Lets see some examples of this in action shall we:

From this example it can be seen that we do indeed need to provide the same types in both branches, otherwise we get a compiler error

image

And here we have another example where we have not supplied an else at all, so we must return unit, but we have broken this rule by attempting to return a string, which again gives us a compiler error

image

Here is the above example fixed with no compiler warnings:

let returnAString x  = if x then "cat" else "dog"

Here is an example that shows a if-elif-else combination.

let compareTheNumbers x y =
    if x = y then "=" 
    elif x < y then "<" 
    else ">"

printfn "%d %s %d" 10 (compareTheNumbers 10 20) 20
printfn "%d %s %d" 20 (compareTheNumbers 20 10) 10
printfn "%d %s %d" 20 (compareTheNumbers 20 20) 2

Which gives this output when run:

image

Sometimes a better approach would be to not use an If Elif Else at all, but rather use a standard pattern match. Here is an example where we have rewritten the last example but have changed it into a function that takes a tuple and uses pattern matching to achieve the same results as if we had of used a If Elif

let compareTheNumbers x =
    match x with
        | (x,y) when x = y -> "=" 
        | (x,y) when x < y -> "<" 
        | (_,_) -> ">"

printfn "%d %s %d" 10 (compareTheNumbers (10,20)) 20
printfn "%d %s %d" 20 (compareTheNumbers (20,10)) 10
printfn "%d %s %d" 20 (compareTheNumbers (20,20)) 20

For

This loop construct is used to iterate over an enumerable collection such as a list/sequence or array. It is similar to foreach in C#.

Here is an example

let sumTheList theList =
    let mutable total=0
    for i in theList do
        total <- total + i
    total
    
let theSum = (sumTheList [1..10])
printfn "The sum of [1..10] is %A" theSum

Though as before there are better (more functional) approaches one could take. For example we could use the many functions already existing in the list/sequence modules, which may alleviate the need to start using loops at all. Here is the above example rewritten using the the standard List module List.sum function.

let theSum = List.sum [1..10]
printfn "The sum of [1..10] is %A" theSum

For..To

It is also possible to do for loops to a certain end condition, and it is also possible to do for loops down to a certain end condition. Here is a small example which demonstrates both of these:

let forUpFunction() =
    printfn "for i = 1 to 10 do\r\n"
    for i = 1 to 10 do
    printf "%d " i
    printfn "\r\n" 

let forDownFunction() =
    printfn "for i = 10 downto 1 do\r\n"
    for i = 10 downto 1 do
    printf "%d " i

    
forUpFunction()
forDownFunction()

Which when run gives the following output

image

While..Do

F# also comes with a familiar While/Do loop construct, which you all would have seen/used in other languages.

Here is a trivial example that prints the index of a number within a source list. This is obviously just for demonstration purposes and you would not use this in real life, you would use List.find and that would be job done, I did however want to demonstrate a while/do loop, so please forgive me.

Here is the code:

let findANumberInAList theList theNum =
    let mutable index = 0;
    let mutable found=false
    let mutable current =0;
    let listHasItem = (List.exists (fun el -> el = theNum) theList)
    if listHasItem then 
        while not found do
            current <- List.nth theList index
            if(current = theNum) then
                printfn "Found %A in source list at index %A" theNum index
                found <- true
            index <- index + 1
                
let sourceList = [1..10]
printfn "SourceList = %A\r\n" sourceList
findANumberInAList [1..10] 4

Which when run produces the following output

image

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)