CSE 130 : Winter 2009 Programming Languages News PA 2 out, and due Mon 1/26 5pm Lecture 5: Functions and Datatypes t UC San Diego Recap: Environments Phone book Variables = names Values = phone number Next: Functions Expressions Values 1. Evaluate: Find and use most recent value of variable Types 2. Extend: let x = e Add new binding at end of phone book Q: What s the value of a function?
Functions Values Functions Values Two questions about function values: Two questions about function values: What is the value: What is the value: 1. of a function? 1. of a function? 2. of a function application (call)? (e11 e2) 2. of a function application (call)? (e11 e2) Values of functions: Closures Free (vs. Bound) Variables Body expression not evaluated until application but type-checking takes place at compile time i.e. when function is defined Function value = <code + environment at definition> closure # let x = 2+2 val x : int = 4 # let f = fun y -> x + y val f : int -> int = fn # let x = x + x val x : int = 8 # f 0 val it : int = 4 Binding used to eval (f ) x 4 : int f fn <code, >: int->int x 8 : int Binding for subsequent x let a = 20 let f x = let y = 1 in let g z = y + z in a + (g x) f 0 Inside a function: A bound occurrence: 1. Formal variable 2. Variable bound in let-in x, y, z are bound inside f A free occurrence: Not bound occurrence a is free inside f Environment at definition, frozen inside closure, is used for values of free variables
Nested function bindings Nested function bindings let a = 20 let f x = let a = 1 in let g z = a + z in a + (g x) f 0; Inside a function: A bound occurrence: 1. Formal variable 2. Variable bound in let-in-end x, a, z are bound inside f A free occurrence: Not bound occurrence nothing is free inside f Environment at definition, frozen inside closure, is used for values of free variables let a = 20 let f x = let a = 1+1 in let g z = a + z in a + (g x) f 0; Q: Where do values of bound variables come from? Bound variable values determined when fun evaluated ( executed ) From arguments Local variable bindings Obtained by evaluation Static/Lexical Scoping Static/Lexical Scoping let a = 20 let f x = let y = 10 in let g z = y + z in a + (g x) f 0; For each var, unique place in prog. text where var is defined Static/Lexical Scope Determined by prog text Without executing prog Easy readability, debugging For each occurrence of a variable, there is a unique place in program text where the variable was defined Most recent binding in environment Static/Lexical: Determined from the program text Without executing the program Very useful for readability, debugging: Don t have to figure out where a variable got assigned Don t have to figure out where a variable got assigned Unique, statically known definition for each occurrence
Values of function application Application: fancy word for call (e1 e2) apply the argument e2 to the (function) e1 Application Value: 1. Evaluate e1 in current env to get (function) v1 v1 is code + env code is (formal x + body e), env is E 2. Evaluate e2 in current env to get (argument) v2 3. Evaluate body e in env E extended by binding x to v2 Example 1 let x = 1 let f y = x + y let x = 2 let y = 3 f (x + y) Example 1 let x = 1 let f y = x + y let x = 2 let y = 3 f (x + y) Example 2 let x = 1 let f y = let x = 2 in fun z -> x + y + z let x = 100 let g =(f 4) g let y = 100 (g 1)
Example 2 let x = 1 let f y = let x = 2 in fun z -> x + y + z let x = 100 let g =(f 4) let y = 100 (g 1) Example 3 let f g = let x = 0 in g 2 let x = 100 let h y = x + y f h Static/Lexical Scoping What about more complex data? For each occurrence of a variable, Unique place in program text where variable defined Most recent binding in environment Expressions Values Static/Lexical: Determined from the program text Without executing the programy Very useful for readability, debugging: Don t have to figure out where a variable got assigned Unique, statically known definition for each occurrence Types Many kinds of expressions: l 1. Simple 2. Variables 3. Functions
What about more complex data? We ve seen some base types and values: Integers, Floats, Bool, String etc. Some ways to build up types: Products (tuples), records, lists Functions Design Principle: Orthogonality Don t clutter core language with stuff Few, powerful orthogonal building techniques Put derived types, values, functions in libraries Next: Building datatypes Three key ways to build complex types/values 1. Each-of types Value of T contains value of T1 and a value of T2 2. One-of types Value of T contains value of T1 or a value of T2 3. Recursive Value of T contains (sub)-value of same type T Suppose I wanted a program that processed lists of attributes Name (string) Age (integer) DOB (int-int-int) Address (string) Height (float) Alive (boolean) Phone (int-int) email (string) Many kinds of attributes: too many to put in a record can have multiple l names, addresses, phones, emails etc. Want to store them in a list. Can I? t Constructing Datatypes type t = C1 of t1 C2 of t2 Cn of tn is a new datatype. A value of type t is either: Or Or Or a value of type t1 placed in a box labeled C1 a value of type t2 placed in a box labeled C2 a value of type tn placed in a box labeled Cn
Suppose I wanted Attributes: type attrib = Name(string) Name of string Age (integer) Age of int DOB (int-int-int) DOB of int*int*int Address (string) Address of string Height (real) Height of float Alive (boolean) Alive of bool Phone (int-int) Phone of int*int email (string) Email of string Creating Values How to create values of type attrib? # let a1 = Name Ranjit val x : attrib = Name Ranjit type attrib = # let a2 = Height 5.83 Name of string val a2 : attrib = Height 5.83 # let year = 1977 Age of int val year : int = 1977 DOB of int*int*int # let a3 = DOB (9,8,year) Address of string val a3 : attrib = DOB (9,8,1977) Height of float # let a_l = [a1;a2;a3] Alive of bool val a3 : attrib list = Phone of int*int t Email of string One-of types We ve defined a one-of type named attrib Elements are one of: string, int, int*int*int, float, bool Can create uniform attrib lists Suppose I want a function to print attribs datatype attrib = Name of string Age of int DOB of int*int*int Address of string Height of real Alive of bool Phone of int*int Email of string; How to tell whats in the box? type attrib = match e with Name of string Name s -> e1 Age of int Age i -> e2 DOB of int*int*int DOB (m,d,y) -> e3 Address of string Address addr -> e4 Height of float Height h -> e5 Alive of bool Phone of int*int Alive b -> e6 Email of string Phone (a,n) -> e7 Email e -> e8 Pattern-match expression: check if e is of the form On match: value in box bound to pattern variable thi lt i i l t d matching result expression is evaluated Simultaneously test and extract contents of box
match-with is an Expression match e with Name s -> e1 Age i -> e2 DOB (m,d,y) -> e3 Address addr -> e4 Height h -> e5 Alive b -> e6 Phone (a,n) -> e7 Email e -> e8 match-with is an Expression match e with C1 x1 -> e1 C2 x2 -> e2 Cn xn -> en Type rules? e1, e2,,enen must have same type Which is type of whole expression Benefits of match-with match e with type t = C1 x1 -> e1 C1 of t1 C2 x2 -> e2 C2 of t2 Cn xn -> en Cn of tn What about Recursive types? type int_list = Nil Cons of int * int_list 1. Simultaneous test-extract-bind 2. Compile-time checks for: missed cases: ML warns if you miss a t value redundant cases: ML warns if a case never matches Think about this! What are values of int_list? Cons(1,Cons(2,Cons(3,Nil))) Cons(2,Cons(3,Nil)) Cons(3,Nil) Nil Cons Cons Cons 1, 2, 3, Nil
Lists aren t built-in in! datatype int_list = Nil Cons of int * int_list Some functions on Lists : Length Base pattern let rec len l = match l with Base Expression Ind pattern Nil -> 0 Cons(h,t) -> 1 + (len t) Inductive Expression Lists are a derived type: built using elegant core! 1. Each-of 2. One-of 3. Recursive :: is just a pretty way to say Cons [] is just a pretty way to say Nil let rec len l = match l with Nil -> 0 Cons(_,t) -> 1 + (len t) Matches everything, no binding let rec len l = match l with Cons(_,t) -> 1 + (len t) _ -> 0 Pattern-matching in order - Must match with Nil Some functions on Lists : Append let rec append (l1,l2) = Base pattern Base Expression Ind pattern Find the right induction strategy Base case: pattern + expression Induction case: pattern + expression Inductive Expression Well designed datatype gives strategy null, hd, tl are all functions Bad ML style: More than aesthetics! Pattern-matching better than test-extract: ML checks all cases covered ML checks no redundant cases at compile-time: fewer errors (crashes) during execution get the bugs out ASAP!
Another Example: Calculator We want an arithmetic calculator to evaluate expressions like: 4.0 + 2.9 = 6.9 3.78 592 5.92 = -2.14 (4.0 + 2.9) * (3.78-5.92) = -14.766 Q: Whats a ML datatype for such expressions? Another Example: Calculator We want an arithmetic calculator to evaluate expressions like: 4.0 + 2.9 = 6.9 3.78 592 5.92 = -2.14 (4.0 + 2.9) * (3.78-5.92) = -14.766 Whats a ML function for evaluating such expressions? Random Art from Expressions PA #2 Build more funky expressions, evaluate them, to produce: