Chapter 6

Imperative Loops

Main Page

Introduction

Because F# supports multi-paradigm development, it supports standard (read imperative) looping constructs.  In general, functional programming favors recursion to imperative looping, in part because it favors zero side effects. For now, we’ll stick to imperative looping structures, and we’ll move into recursive loops in subsequent chapters.

Imperative Looping Constructs

F# supports two types of imperative loops that are familiar in style and content to loops in imperative and OO languages like C# and Java.

·         for…do

·         while…do

for…do Loops

for…do loops enable you to iterate over a range of values. A for…do loop takes the following general form:

for identifier = start [ to | downto ] finish do
   body-expression

 

Let’s look at some examples:

// Output the numbers from 1-10. Note you do not
// need to declare the loop variable with let.

for i = 1 to 10 do

    printfn "i = %d" i

// Count from 1 to 10, with identifiers
let a, b = 1, 10
for k = a to b do
    printfn "k = %d" k

// Count down from 10 (down) to 1
for j = 10 downto 1 do
   
printfn "j = %d" j

// Sum the first 5 non-zero integers.
// This is quite "imperative." We'll see its functional cousin later.
let mutable sum = 0
for n = 1 to 5 do
    sum <- sum + n
    printfn "current sum = %d" sum

F# for loops are technically expressions. They evaluate to unit.

There is another form of the for loop, called for…in, that is used to iterate over collections. We will cover this form of the for loop in the chapter covering collections.

while..do Loops

The while…do loop is an expression used to perform iterative execution so long as a given Boolean condition evaluates to true. The while…do loop takes the following general form:

while test-expression do
    body-expression

In while…do loops, the test expression is evaluated and must resolve to true or false. If the expression evaluates to true, F# executes the body of the loop at least once. After executing the body of the loop, F# reevaluates the test expression. If the test expression evaluates to true, the body is executed again. This process repeats until the test expression evaluates to false. The test expression can be composed of multiple Boolean conjunctions, and can use parentheses and logical operators to group sub-expressions and to force evaluation order. Follow are a few examples of the while…do loop in action:

// Output numbers from 1-10 and squares
let mutable n = 1
while n <= 10 do
   
let sq = n * n
   
printfn "%d %d" n sq
   
n <- n + 1

// Note mutable applies to both identifiers below
let mutable a, b = 1, 10
while b > a do
    printfn "%d %d" a b
    a <- a + 1
    b <- b - 1

// Using parentheses and Boolean conjuction  
let mutable a, b, c = 1, 10, 0
while ((a < b) && (c < 3)) do
   
printfn "%d %d %d" a b c
   
c <- c + 2

// WARNING: Infinite loop ahead!
while (true) do
   
printfn "F# is great!" 

If you’re running F# code in the F# Interactive Console, and you’ve accidentally coded an infinite loop, you can abort the loop via pressing Ctrl-. (Control-period).

// WARNING: Body never executes
while (false) do
   
printfn "This will never be output!"

Unlike other programming languages, F# does not currently support unconditional loop termination statements such as C#’s break and continue statements.  However, we should point out that the F# reference documentation says that the keywords ‘break’ and ‘continue’ are reserved for future use.

What You Need to Know

·         As a multi-paradigm language, F# supports imperative looping constructs in the form of for…do and while…do loops.

·         for…do loops are generally used to iterate a fixed number of times, e.g., from 1 – 10 or from 100 down to 0.

·         while…do loops are generally used to iterate as long as a given expression evaluates to true.

·         Unlike other languages, F# imperative loops do not currently support unconditional jumps, e.g., like C#’s break and continue statements.

·         Although it supports imperative looping, F# tends to favor recursive looping due to the fact that recursion limits side effects. We will see examples of recursive looping in subsequent chapters.

 

Feedback

We welcome your feedback. If you have comments or questions about this chapter, please feel free to e-mail us at

Keep Reading

Next Chapter...