Loops
Prerequisites: Lists
F# has loops for when you want to do something repeatedly — print,
write to a file, update a mutable value. To compute a new collection,
prefer List.map, List.filter, and friends.
for ... in
for fruit in ["apple"; "banana"; "cherry"] do
printfn "I like %s" fruit
for i in 1 .. 3 do
printf "%d " i
printfn ""
for i in 10 .. -3 .. 1 do
printf "%d " i
printfn ""
for (name, age) in [("Ada", 36); ("Alan", 41)] do
printfn "%s is %d" name age
I like apple
I like banana
I like cherry
1 2 3
10 7 4 1
Ada is 36
Alan is 41
for ... in works with any sequence, a range (1 .. 3), or a range
with a step (10 .. -3 .. 1), and can destructure tuples.
for ... to
for i = 1 to 3 do
printf "%d " i
for i = 3 downto 1 do
printf "%d " i
printfn ""
1 2 3 3 2 1
while
let mutable n = 27
let mutable steps = 0
while n <> 1 do
n <- if n % 2 = 0 then n / 2 else 3 * n + 1
steps <- steps + 1
printfn "Reached 1 after %d steps" steps
Reached 1 after 111 steps
No break or continue
F# loops have no break or continue. Instead, use a while loop with
a condition flag, or — more idiomatic — a collection function that stops
early:
let numbers = [3; 8; 12; 5; 20]
// "find the first number over 10" — no loop needed
printfn "%A" (numbers |> List.tryFind (fun n -> n > 10))
// "skip the odd ones" — filter instead of continue
for n in numbers |> List.filter (fun n -> n % 2 = 0) do
printf "%d " n
printfn ""
Some 12
8 12 20
Loops versus functions
// Loop style
let mutable total = 0
for n in 1 .. 100 do
if n % 3 = 0 then total <- total + n
printfn "%d" total
// Functional style
[1 .. 100] |> List.filter (fun n -> n % 3 = 0) |> List.sum |> printfn "%d"
1683
1683
Both are correct. The functional version has no mutable state and says what it computes; F# programmers generally reach for it first.
Practice
Print a 5-row triangle of stars (*, **, ... *****) using a for
loop and String.replicate.
Show solution
for i in 1 .. 5 do
printfn "%s" (String.replicate i "*")
*
**
***
****
*****