CS 541 Lecture -*- Outline -*- * Name binding and scope (have made a homework some years) objective: to get across the notions of: sugars (as way of explaining semantics) and simultaneous bindings scope Boil everything down to lambda and case ** pattern matching in function defs is sugar for case (Davie pp. 29 and 190) Q: How could one define the semantics of Haskell function defs with complex features like guards and pattern matching? One way ------------------------------------------ FUNCTION DEFINITION SEMANTICS The problem: function defs can be complex > fact 0 = 1 > fact n | n > 0 = n * fact(n-1) > while test f x > | b = while test f (f x) > | otherwise = x > where b = test x > quotient(i,j) = lastq > where (lasti,lastq) = > (while notdone xform (i,0)) > notdone (i,q) = (i >= j) > xform (i,q) = (i-j,q+1) what does this all mean? ------------------------------------------ Q: What features are being used? We'd like an explanation for each feature that is: - syntax-directed (based on the syntax), like a yacc-based compiler and - "adds up" to an explanation for the whole thing Such an explanation is *compositional*. (this is unlike English) compositional vs. Non-compositional examples: red book, red ball vs. red herring, red neck, hockey player, baseball player vs. CD player day room, dark room vs. rest room pro vs. con ==> progress vs. congress (;->) train station, bus station vs. work station (;->) ------------------------------------------ SYNTACTIC SUGARS AN EXPLANATORY DEVICE def: a feature of a language is a *syntactic sugar* if Example: fact 0 = 1 fact n | n > 0 = n * fact(n-1) ==> ------------------------------------------ ... each occurrence of that syntax can be regarded as macro call and replaced by some other piece of syntax ... fact = (\ x -> (case x of 0 -> 1 n -> if n > 0 then n * fact(n-1) else error "Unmatched pattern")) discuss the meaning of the case, pattern match from the top ------------------------------------------ PATTERN GUARDS SUGAR FOR IF (D 2.7.1) Guard desugaring:

| 1 = 1 | 2 = 2 ... | n = n where { } ==> FOR YOU TO DO Desugar: while test f x | b = while test f (f x) | otherwise = x where b = test x ------------------------------------------ ...

= let in if 1 then 1 else if 2 then 2 else ... if n then n else error "Unmatched guard" ------------------------------------------ SYNTACTIC SUGAR FOR IF if 1 then 2 else 3 ==> case 1 of True -> 2 False -> 3 ------------------------------------------ ------------------------------------------ MULTIPLE BINDING IS SUGAR FOR CASE Function binding form:

11 ...

1n = 1 ...

m1 ...

mn = m ==> FOR YOU TO DO desugar the following > name 0 = "zero" > name 1 = "one" > name n = "many" ------------------------------------------ ... x1 ... xn = case (x1,...,xn) of (

11, ...

1n) -> 1 ... (

m1, ...

mn) -> m (where x1 ... xn are fresh) ------------------------------------------ FUNCTION DEFINITION SUGAR FOR LAMBDA x1 ... xn = E ==> Example: compose (f,g) x = f (g x) ==> ------------------------------------------ ... x1 ... xn-1 = (\ xn -> E) and so get = (\x1 -> (...(\xn -> E)...)) ... compose = (\(f,g) -> (\x -> f (g x))) Now patterns only occur in case expressions and lambdas ------------------------------------------ GETTING PATTERNS OUT OF LAMBDAS ucompose (f,g) x = f (g x) ==> ucompose = \ (f,g) -> \ x -> f (g x) ==> ------------------------------------------ ucompose = \ fg -> case fg of (f,g) -> \x -> f (g x) ** simultaneous binding, lexical scope (D 2.4) ------------------------------------------ SCOPE FOR DECLARATIONS AND LET > x = u + v > y = u - v > (u,v) = (4,5) :: (Integer, Integer) let x1 = u1 + v y1 = u1 - v u1 = 4 :: Integer in [x1,y1,u1,v] ------------------------------------------ draw contour for scope of x,y,u,v includes all of the parts of the program after the = draw contour for scope of x1,y1,u1 includes the right-hand sides and the body (like letrec) Q: What's this like in Scheme? Q: What will that expression's value be? everything is lazy, order doesn't matter. then bindings made simultaneously ------------------------------------------ SYNTACTIC SUGAR FOR LET (dynamic behavior, not typing) let

1 = 1 ...

n = n in 0 ==> let (~

1, ..., ~

n) = (1, ..., n) in 0 let

= 1 in 0 ==> let

= fix (\ ~

-> 1) in 0 let

= 1 in 0 -- if no var in

occurs -- free in 1 ==> ------------------------------------------ ... (\ ~

-> 0) 1 This last is like Scheme let, and even it gets desugared to a case... The ~ makes an irrefutable binding: that is, a lazy one compare scope of result with the original scope. ** Binding vs. assignment (skip) in Haskell, only bindings, no changes to existing bindings, but can make holes in their scope. => referential transparency :=, assignment binds name to cell, 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)