## Referential transparency again

``````let x = 0 in
let f y = x+y in
(f 1) + (f 1)``````
``````let x = 0 in
let f y = x + y in
let z = (f 1) in z+z``````

These expressions are equivalent in any context. But in ‘not-Ocaml’:

``````let x = 0 in
let f y = {
x := x+y ;
x
} in
(f 1) + (f 1)``````
``````let x = 0 in
let f y = {
x := x+y;
x
} in
let z = (f 1) in z+z``````

Assignments can eliminate referential transparency

# lies

## OCaml has assignment

``````let x = ref 0 in
let f y =
let () = x := (!x)+y in !x in
(f 1) + (f 1)``````

OCaml supports typed references, which refer to memory cells on the heap. The type rules for references are:

``````e : τ ⇒ ref e : τ ref
e : τ ref ⇒ !e : τ
x : τ ref, e : τ ⇒ x := e : unit``````

Notice that with references, order of evaluation is important

## Ordering evaluations

We can force OCaml to evaluate a sequence of expressions in order using nested lets:

``````let _ = e1 in
let _ = e2 in (* ... *)
let _ = en in e``````

OCaml provides a shorthand for this:

``e1; e2; (* ... *) en; e``

Note 1: `;` is a separator, not a terminator.
Note 2: you’ll get a compiler warning if any of `e1`, `e2`, …, `en` does not have type `unit`.

## Ordering evaluations

What about operators and function calls?

``````let a = ref "A" in
let b = ref "B" in
(a := "C"; !a) ^ (b := !a ^ !b; !b)``````

In OCaml, this is specified but the programmer must know; the behavior of `f(++x,x++);` is “implementation specific” in C!

Despite these drawbacks, some things are easiest to compute with assignment.

# `lazy`

Example: “under the hood” of the `Lazy` module:

``````type 'a lcell = V of 'a | L of (unit -> 'a)
type 'a t = 'a lcell ref
let force lz = match !lz with
| L thunk -> let v = thunk () in lz := V v ; v
| V v -> v
let make_lazy thunk = ref (L thunk)``````

# Memoization

``````let memo f =
let ft = ref [] in
fun x ->
try List.assoc x ft with
| Not_found -> let fx = f x in
ft := (x,fx)::!ft; fx``````
``````let memofib =
let fibt = ref [] in
let rec mfib n =
try List.assoc n !fibt with
| Not_found -> if n < 2 then n else
let fn = (mfib (n-1)) + (mfib (n-2)) in
fibt := (n,fn)::!fibt; fn
in mfib``````

## Value Restriction

References are a common source of “monomorphic type variables:”

``````# let r = ref [] ;;
val r : '_weak1 list ref = ...
# r := [1] ;;
- : unit = ()
# r ;;
val r : int list ref = ...``````

Only immutable values can have polymorphic type in OCaml…

# `cs2041.org`

// reveal.js plugins