Yao Lirong's Blog

Mutability

2020/03/03

From Textbook: Mutability


Refs

Syntax

1
2
3
ref x
!x
x := e
  • ref x: creates a reference using the ref keyword (let x = ref 0 creates a location in memory whose contents are initialized to 0)
  • !x: dereferences x and returns the contents of the memory location
  • x := e: is an assignment. It mutates the contents x to be 1. Note that x itself still points to the same location (i.e., address) in memory. Variables really are immutable in that way. What changes is the contents of that memory location. Memory is mutable; variable bindings are not.

Counter

1
2
3
4
5
6
7
8
9
10
11
12
13
let next_val = 
let counter = ref 0
in fun () ->
incr counter;
!counter

let next_val_broken = fun () ->
let counter = ref 0
in incr counter;
!counter

next_val_broken () = 1 ... 1 ... 1
next_val () = 1 ... 2 ... 3 ...

Look at how these two functions’ results differ. In the first example, counter is just a temporary variable later bound to the fun() -> ... Therefore, counter will not be initiated every time we call next_val . It is evaluated only when the first time it is defined.

Sequencing

1
e1; e2; ... ; en

The sentence above evaluates each one of ei in order from left to right, returning only vn.

If the values vi previous expression ei evaluates to are not of type unit, the compiler will give you a warning because it makes no sense to throw away those values. To get rid of the warning (if you’re sure that’s what you need to do), there’s a function ignore : 'a -> unit in the standard library. Using it, ignore(2+3); 7 will compile without a warning. Of course, you could code up ignore yourself: let ignore _ = ().

This is a syntactic sugar of let _ = e1 in e2

Equality

  • Physical Equality (==,!=): same address
  • Structural Equality (=,<>): same content

Mutable Fields (in Record)

Syntax

1
2
3
4
5
6
7
8
9
(* declare a record with mutable field *)
type point = {x:int; y:int; mutable c:string}
let p = {x=0; y=0; c="red"}

(*mutate the field of that record*)
p.c <- "white"

p.x <- 3
# Error: The record field x is not mutable

Mutable Stack

Arrays and Loops

Arrays

  • Array creation: [|e0; e1; ...; en|]
  • Array indexing: e1.(e2)
  • Array assignment: e1.(e2) <- e3

Loops

1
2
3
4
5
6
7
8
9
10
while e1 do e2 done

let i = ref 0
while !i<=2 do print_endline(string_of_int v.(!i)); incr i done

for x=e1 to e2 do e3 done
for x=e1 downto e2 do e3 done

for i=1 to 2 do print_endline(string_of_int v.(i)) done
for i=2 downto 0 do print_endline(string_of_int v.(i)) done
  • while loops terminate when e1 becomes false

  • for loops execute once for each integer from e1 to e2

  • for..to loops evaluate starting at e1 and incrementing x each iteration; for..downto loops evaluate starting at e1 and decrementing x each iteration

CATALOG
  1. 1. Refs
    1. 1.1. Syntax
    2. 1.2. Counter
  2. 2. Sequencing
  3. 3. Equality
  4. 4. Mutable Fields (in Record)
    1. 4.1. Syntax
    2. 4.2. Mutable Stack
  5. 5. Arrays and Loops
    1. 5.1. Arrays
    2. 5.2. Loops