(* Code for Lecture 2: Binding, Scope, Functions *) (* pi up to 2 digits *) val pi : real = 3.14; val area : real -> real = fn (r:real) => pi * r * r; val a2 = area (2.0); (* We can shadow the definition of pi. *) val pi : real = 6.0; (* The area function will remain unchanged. *) val a3 = area (2.0); (* We can shadow area with a more accurate definition. *) val pi : real = Math.pi; fun area (r:real) = pi * r * r; (* A function of two arguments is actually a function taking a pair as argument. *) (* power(n,k) = n^k for k >= 0 where 0^0 = 1 *) (* power : (int * int) -> int *) fun power (n:int, k:int) = if k = 0 then 1 else n * power (n, k-1); (* Checking the invariant (here: k >= 0) each time around the loop is often inefficient. *) exception Domain; (* powerSlow(n,k) like power(n,k), but raises Domain if k < 0 *) fun powerSlow (n:int, k:int) = if k < 0 then raise Domain else if k = 0 then 1 else n * powerSlow (n, k-1); (* Better is to check the invariant for the externally visible function only, and not during recursion. *) (* powerExport(n,k) like power(n,k), but raises Domain if k < 0 *) fun powerExport (n:int, k:int) = if k < 0 then raise Domain else power (n, k);