(* 15-212, Spring 2011 *) (* Michael Erdmann *) (* Code for Lecture 2: Binding, Scope, Functions *) (************************************************************************) (* pi up to 2 digits *) val pi : real = 3.14; (* Local bindings *) let val m:int = 3 val n:int = m*m in m*n end; (* Do you understand the scope of "k" in the code below? *) (* What are the three values of the three expressions? *) val k : int = 4; let val k : int = 3 in k*k end; k; (* Functions *) val area : real -> real = fn (r:real) => pi * r * r; val a2 : real = area (2.0); (* We can shadow the definition of pi. *) val pi : real = 6.0; (* The area function will remain unchanged. *) val a3 : real = area (2.0); (* We can shadow area with a more accurate definition. *) val pi : real = Math.pi; fun area (r:real):real = pi * r * r; val a4 : real = area (2.0); (* A function of two arguments is actually a function taking a pair as argument. *) (* val add : int * int -> int add(x, y) ==> x + y Invariants: none Effects: none *) fun add(x:int, y:int) : int = x + y; (* A function can take another function as argument *) (* val sqrf : (real -> real) * real -> real sqrf(f, x) ==> f(x) * f(x) Invariants: none Effects: none *) fun sqrf(f:real->real, x:real) : real = f(x) * f(x); sqrf(Math.sin, 0.7853981634); (* Returning a pair *) (* Type definitions are transparent to type-checking *) type float = real; type point = float * float; (* val reflect: point->point reflect(x,y) ==> (x, ~y), i.e., the point (x, y) is reflected about the x-axis. Invariants: none Effects: none *) fun reflect ((x,y):point) : point = (x, ~y); (* Recursive Functions *) (* val fact:int->int fact(n) ==> n! Invariant: n >= 0 Effects: none *) val rec fact:int->int = fn(n:int) => if n = 0 then 1 else n*fact(n-1); (* Here is a slightly less cumbersome way of writing this: *) fun fact(n:int):int = if n = 0 then 1 else n*fact(n-1); (* Checking the invariant (here: n >= 0) each time around the loop is often inefficient. *) exception Domain; fun fact(n:int):int = if n < 0 then raise Domain else if n = 0 then 1 else n*fact(n-1); (* Better to check the invariant for the externally visible function only, and not during recursion. *) fun fact(n:int):int = let fun f(n:int):int = if n = 0 then 1 else n*f(n-1) in if n < 0 then raise Domain else f(n) end; (************************************************************************)