Imperative programming expresses computation as a sequence of lower-level instructions: create data, iterate through values, branch on conditions, and update program state. It emphasizes how to achieve a result rather than only what result is wanted. section 2.1.1
This style makes control flow explicit, but simple collection queries can become verbose and harder to read. Mutable data and side effects can also make repeated execution produce unwanted accumulated results. section 7.2.1
Filtering and aggregating results
An imperative filter creates an output list, visits each number, checks its condition, and appends matching values. An imperative sports query similarly loops through results, updates a mutable summary, and then searches for the largest count. section 2.1.1 section 7.2.1
IEnumerable<int> GetEvenNumbers(IEnumerable<int> numbers) #1
{ #1
var output = new List<int>(); #1
foreach (var number in numbers) { #1
if (number % 2 == 0) #1
output.Add(number); #1
} #1
return output; #1
} #1
let getEvenNumbers = #2
Seq.filter (fun number -> number % 2 = 0) #2
Compare explicit C#-style iteration and list mutation with the equivalent F# filtering expression. section 2.1.1
Listing 7.2 An imperative query implementation
type TeamSummary = { Name : string; mutable AwayWins : int }
let summary = ResizeArray<TeamSummary>() #1
for result in results do
if result.AwayGoals > result.HomeGoals then #2
let mutable found = false
for entry in summary do #3
if entry.Name = result.AwayTeam then
found <- true
entry.AwayWins <- entry.AwayWins + 1
if not found then #4
summary.Add { Name = result.AwayTeam; AwayWins = 1 }
let mutable wonAwayTheMost = summary[0]
for row in summary do #5
if row.AwayWins > wonAwayTheMost.AwayWins then wonAwayTheMost <- row
Trace the imperative query implementation through mutable summaries, nested loops, conditional insertion, and maximum selection. section 7.2.1













