Side Effects Quick ref review ----------------------- A ref is value which give is the address of another value in memory. Refs are very similar to c/c++ pointers, however sml refs are type safe and and garbage collected. you can create a ref like this - val r = ref 42; val r = ref 42 : int ref If you evaluate r the interpreter returns a reference to 42 - r; val it = ref 42 : int ref To get the value which is refered to, use the ! (bang) operator - !r; val it = 42 : int While a ref will always refer to the same spot in memory, the value found at that address may change. We can update a memory location with the assignement operator, :=. Please note the return type is of assignment is unit. - r := 312; val it = () : unit - !r; val it = 312 : int Furthermore, two refs may refer to the same location in memory. - r := 312; val it = () : unit - val s = r; val s = ref 312 : int ref - r := 31415926; val it = () : unit - !s; val it = 31415926 : int Types of Refs ------------------------ You can make a reference to any sort of value. This fits well with the ML type system's parametric polymorphism. We can think of ref's as being defined with the following signature: type 'a ref; val ref: 'a -> 'a ref val op:= : 'a ref * 'a -> unit val op! : 'a ref -> 'a We can think of the 'a ref type as something like: datatype 'a ref = loc of int While it may tempting to drop the 'a and just make a sing ref type: datatype ref = loc of int this approach does not give the type system enough information to check that all !s, :=s and ref(..) are ok. Substitution Model -------------------------- Last year's lecture notes have an exmaple of using the substitution model to reason about refs. http://www.cs.cornell.edu/courses/cs312/2003sp/lectures/rec16.html Environment Model -------------------------- Slides at http://www.cs.cornell.edu/courses/cs312/2003sp/lectures/lec18.ppt cover details on using the environment with refs. I think it's best to teach by example... A few things to work through with the environment model: A simple example: let val x = ref 2 in val y = x in x:=1; !y end Building a recursive loop using ref: let val x = ref (fn x:int => x) val f = fn n:int => if n <= 1 then 1 else n * (!x)(n-1) in x := f; f 3 end Using side effects to make a cuter stream: type 'a stream = unit -> 'a option; let fun newIntStream(low: int, high: int): int stream = let val i = ref low in fn() => let val old = !i in if(old <= high) then (i:=old+1; SOME (old)) else NONE end end val foo = newIntStream(103,105) val x = foo() val y = foo() val z = foo() in case(x,y,z) of (SOME a, SOME b, SOME c) => a+b+c | _ => raise Fail "opps!" end