CS 541 Lecture -*- Outline -*- * Name bindings statically scoped objective: to get across the notions of: sugars simultaneous vs. sequential bindings, scope environment ** pattern matching in fun is sugar for case (p.112) --------------- PATTERN SUGARS fun fact 0 = 1 | fact n = n * fact(n-1); (* equivalent to *) fun fact x = (case x of 0 => 1 | n => n * fact(n-1)); ----------------- discuss the meaning of the case, pattern match from the top ** top-level binding: val (sections 2.1, 2.2) val name = E binds name to the value of E, doesn't complain if name already has a binding *** redefinition (sequential bindings) --------------- SEQUENTIAL BINDINGS - val x = 3; val x = 3 : int - val y = x + 1; val y = 4 : int - val x = x + 1; val x = 5 : int - x; val it = 5 : int ----------------- can be used for redefinition, redefinition useful for debugging redefinition makes a new environment, old one still exists val x = 3; global env --> [x: 3] val x = 5; global env \ [x: 3] \-> [x: 5] -------------------------- - fun inc5(y) = y + x; val inc5 = fn : int -> int - val x = 7; val x = 7 : int - inc5(10); val it = 15 : int --------------------------- redefinition doesn't work like assignment from *inside* a program, makes a new binding instead of changing one in surrounding scope. --------------------------------------- - fun foo() = let val x = 4 in x end; val foo = fn : unit -> int - foo(); val it = 4 : int - x; val it = 7 : int ------------------------- this shows that val doesn't do asignment *** simultaneous bindings expressions on right all evaluated, then bindings made simultaneously --------------- SIMULTANEOUS BINDINGS - val x = 3 and y = 4; val x = 3 : int val y = 4 : int - val x = y and y = x; val x = 4 : int val y = 3 : int - val (x,y) = (y,x); val x = 3 : int val y = 4 : int ----------------------------- the second one really gives the key idea: evaluate the right hand sides, then bind it's equivalent to the third note this is the way to do mutual recursion too. ------------------------------ - fun odd(0) = false | odd(n) = even(n - 1) and even(0) = true | even(n) = odd(n - 1); val odd = fn : int -> bool val even = fn : int -> bool --------------- ** program (nestable) forms *** let hides declarations within an expression **** sequential bindings let val x1 = e1 in E end =def= ((fn x1 => E) e1) -------------- LET EXPRESSIONS - let val x = 3 in x+1 end; val it = 4 : int - ((fn x => x+1) 3); val it = 4 : int - let val x = 33 (* optional ; *) val y = x + 2; val z = y * x in z * z end; val it = 1334025 : int -------------- let val x1 = e1 val x2 = e2 ... val xn = en in E end =def= let val x1 = e1 in let val x2 = e2 ... val xn = en in E end end sequential binding of names can use x1 in x2, etc. Q: Can you use let to write a tail recursive version of member? **** simultaneous bindings ---------------------------- let val x = 3 and y = 4 in let val y = x and x = y in [x,y] end end; ---------------------------- let val x1 = e1 and x2 = e2 ... and xn = en in E end =def= ((fn (x1,x2,...,xn) => E) (e1,e2,...,en)) simultaneous local binding of names (note that the xi cannot be used in defining the other xj) *work examples* *** local -------------------------- LOCAL vs. LET let allows decls within expression let val x = 3 in x * x * x end; local allows decls within decls local val x = 3 in val twentyseven = x * x * x end; local val pi_over_4 = 3.14159/4.0 in fun cosine ang = ... pi_over_4 ... end; -------------------------- hides declarations in a declaration see the book for details. ** Binding vs. assignment *** references and assignment (chapter 8) val x = ref 3; now x has type: int ref that is, x denotes a cell (location) that can be changed x := e2 mutates the cell denoted by x. x must be defined already !x gets value out of cell denoted by x -------------- REFERENCES - val x = ref 3; val x = ref 3 : int ref - x := 4; val it = () : unit - x; val it = ref 4 : int ref - !x; val it = 4 : int -------------- *** differences let sets up a binding, does not change existing bindings => referential transparency := makes assignment no referential transparency what's bound to what: name bound to value, because 3 may be value of several names the binding is a property of the name (not 3)