Skip to article frontmatterSkip to article content

Mutability

Cornell University

From Textbook: Mutability


Refs

Syntax

ref x
!x
x := e

Counter

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

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

Mutable Fields (in Record)

Syntax

(* 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

Loops

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