Skip to content
AgileLogics
5 min read

Values and Immutability

Prerequisites: Your first program

let gives a name to a value:

let city = "Lagos"
let temperature = 24
printfn "It is %d degrees in %s" temperature city

let warmer = temperature + 3
printfn "Tomorrow: %d" warmer
It is 24 degrees in Lagos
Tomorrow: 27

A let binding is immutable — once temperature is 24, it stays 24. Instead of changing values, F# code usually computes new ones (warmer). This makes programs easier to reason about: a value you read on line 3 is the same value on line 300.

= is not assignment

Outside let, = means comparison, so trying to "reassign" a value compares it instead:

let score = 10
let result = (score = 11)
printfn "%b" result
false

Shadowing

Inside a function (you'll write your own in a few lessons), you can define a new value with the same name. The new one shadows the old one from that point on:

let parseCount (input: string) =
    let input = input.Trim()
    let input = input.TrimStart('0')
    int input

printfn "%d" (parseCount "  0042 ")
42

Shadowing doesn't change the old value — it makes a new binding. It's handy for step-by-step cleanup of the same piece of data.

At the top level of a script or source file, though, each name can be defined only once:

let text = "  42 "
let text = text.Trim()
main.fsx(2,5): error FS0037: Duplicate definition of value 'text'

mutable

When you really need a variable that changes, use mutable and the <- operator:

let mutable count = 0
count <- count + 1
count <- count + 1
printfn "count = %d" count
count = 2

mutable is fine for local counters and performance-sensitive loops. Most F# code rarely needs it — you'll see alternatives (recursion, folds, pipelines) throughout this course.

Naming

Values and functions use camelCase (totalPrice); types and modules use PascalCase (ShoppingCart). Names can contain an apostrophe — x' is a common name for "the next version of x".

Practice

Create a value price of 20 and a value quantity of 3, compute total, then compute discounted with 5 subtracted. Use a mutable value orders that starts at 0 and goes up by one. Print everything on one line.

Show solution
let price = 20
let quantity = 3
let total = price * quantity
let discounted = total - 5
let mutable orders = 0
orders <- orders + 1
printfn "%d -> %d (orders: %d)" total discounted orders
60 -> 55 (orders: 1)