Presentation is loading. Please wait.

Presentation is loading. Please wait.

ML Again ( Chapter 7) Patterns Local variable definitions

Similar presentations


Presentation on theme: "ML Again ( Chapter 7) Patterns Local variable definitions"— Presentation transcript:

1 ML Again ( Chapter 7) Patterns Local variable definitions
Two sorting examples The implementation using functional languages is closer to the concepts of the solutions. 7/2/2018 IT 327

2 Both n and (a,b) are patterns.
fun f n = n*n; fun g (a,b) = a*b; Both n and (a,b) are patterns. n is a pattern of integers; (a, b) is a pattern of 2-tuple of integers. For match and bind (most of the time) f 2; (matched) f (2,3); (not matched) g 2; (not matched) g (2,3); (matched) IT 327 7/2/2018

3 Underscore is a Pattern
- fun f _ = "yes"; val f = fn : 'a -> string - f 34.5; val it = "yes" : string - f []; The underscore matches anything, but does not bind it to a variable fun f x = "yes"; 7/2/2018 IT 327

4 Constants are Patterns
- fun f 0 = "yes"; Warning: match nonexhaustive 0 => ... val f = fn : int -> string - f 0; val it = "yes" : string Any constant of an equality type can be used as a pattern But not: fun f 0.0 = "yes"; 7/2/2018 IT 327

5 Non-Exhaustive Match “match non-exhaustive” warning
Meaning: f was defined using a pattern that didn’t cover all the domain type (int) So you may get runtime errors like this: - f 0; val it = "yes" : string - f 1; uncaught exception nonexhaustive match failure 7/2/2018 IT 327

6 Lists Of Patterns As Patterns
- fun f [a,_] = a; Warning: match nonexhaustive a :: _ :: nil => ... val f = fn : 'a list -> 'a - f [#"f",#"g"]; val it = #"f" : char You can use a list of patterns as a pattern This example matches any list of length 2 It treats a and _ as sub-patterns, binding a to the first list element Why not 1? 7/2/2018 IT 327

7 Cons Of Patterns As A Pattern
- fun f (x::xs) = x; Warning: match nonexhaustive x :: xs => ... val f = fn : 'a list -> 'a - f [1,2,3]; val it = 1 : int You can use a cons of patterns as a pattern x::xs matches any non-empty list, and binds x to the head and xs to the tail Parentheses around x::xs are for precedence 7/2/2018 IT 327

8 Little Summary A variable is a pattern that matches anything, and binds to it A _ is a pattern that matches anything A constant (of an equality type) is a pattern that matches only that constant A tuple of patterns is a pattern that matches any tuple of the right size, whose contents match the sub-patterns A list of patterns is a pattern that matches any list of the right size, whose contents match the sub-patterns A cons (::) of patterns is a pattern that matches any non-empty list whose head and tail match the sub-patterns 7/2/2018 IT 327

9 Multiple Patterns for Functions
- fun f 0 = "zero" = | f 1 = "one"; Warning: match nonexhaustive 0 => ... 1 => ... val f = fn : int -> string; - f 1; val it = "one" : string You can define a function by listing alternate patterns 7/2/2018 IT 327

10 Syntax To list alternate patterns for a function
<fun-def> ::= fun <fun-bodies> ; <fun-bodies> ::= <fun-body> <fun-bodies> ::= <fun-body> | <fun-bodies> <fun-body> ::= <fun-name> <pattern> = <expression> To list alternate patterns for a function You must repeat the same function name in each alternative We just hit the limitation of CFG 7/2/2018 IT 327

11 Overlapping Patterns Patterns may overlap
- fun f 0 = "zero" = | f _ = "non-zero"; val f = fn : int -> string; - f 0; val it = "zero" : string - f 34; val it = "non-zero" : string Patterns may overlap ML uses the first match for a given argument 7/2/2018 IT 327

12 Pattern-Matching Style
Two alternatives: fun f 0 = "zero" | f _ = "non-zero"; fun f n = if n = 0 then "zero" else "non-zero"; Pattern-matching style is preferred in ML shorter and more legible 7/2/2018 IT 327

13 Pattern-Matching Examples
fun fact n = if n = 0 then 1 else n * fact(n-1); fun fact 0 = 1 | fact n = n * fact(n-1); fun reverse L = if null L then nil else reverse(tl [hd L]; fun reverse nil = nil | reverse (first::rest) = reverse 7/2/2018 IT 327

14 A Restriction How to explain this? This is not legal, but why?
fun f (a,a) = … | f (a,b) = … This is not legal, but why? fun f (a,b) = if (a=b) then … else … 7/2/2018 IT 327

15 Patterns in val - val (a,b) = (1,2.3); val a = 1 : int
val b = 2.3 : real - val a::b = [1,2,3,4,5]; Warning: binding not exhaustive a :: b = ... val b = [2,3,4,5] : int list 7/2/2018 IT 327

16 Local Variable Definitions
<let-exp> ::= let <definitions> in <expression> end - let val x = 1 val y = 2 in x+y end; val it = 3 : int; - x; Error: unbound variable or constructor: x let val x = 1 val y = 2 in x+y End; This alone is not very useful! We can put it into a function definition 7/2/2018 IT 327

17 Long Expressions with let
fun days2ms days = days*24.0*60.0*60.0*1000.0; fun days2ms days = let val hours = days * 24.0 val minutes = hours * 60.0 val seconds = minutes * 60.0 in seconds * end; 7/2/2018 IT 327

18 Merge Sort You should have known this well. 3 5 7 8 1 2 6
(if you have taken 279) Merge two sorted lists 3 5 7 8 1 2 6 7/2/2018 IT 327

19 Merge Sort 7 5 3 8 2 1 6 7 5 3 8 2 1 6 7 5 3 8 2 1 6 7 5 3 8 2 1 5 7 3 8 1 2 3 5 7 8 1 2 6 1 2 3 5 6 7 8 7/2/2018 IT 327

20 How to split 7 5 3 8 2 1 6 7 5 3 8 2 1 6 In ML, it’s a bit difficult to do this We have hd, tl and :: 7 5 3 8 2 1 6 7 3,8,2,1,6 5 Recursively 7/2/2018 IT 327

21 halve fun halve nil = (nil, nil) | halve [a] = ([a], nil)
| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end; -halve [1]; val it = ([1],[]) : int list * int list halve [1,2]; val it = ([1],[2]) : int list * int list - halve [1,2,3,4,5,6]; val it = ([1,3,5],[2,4,6]) : int list * int list 7/2/2018 IT 327

22 merge Recursively 7 xs 5 ys 5
fun merge (nil, ys) = ys | merge (xs, nil) = xs | merge (x::xs, y::ys) = if (x < y) then x :: merge(xs, y::ys) else y :: merge(x::xs, ys); 7/2/2018 IT 327

23 Merge Sort int list -> int list, fun mergeSort nil = nil
| mergeSort [a] = [a] | mergeSort theList = let val (x, y) = halve theList in merge(mergeSort x, mergeSort y) end; int list -> int list, 7/2/2018 IT 327

24 Merge Sort At Work These two functions can be defined locally.
- fun mergeSort nil = nil = | mergeSort [a] = [a] = | mergeSort theList = = let = val (x, y) = halve theList = in = merge(mergeSort x, mergeSort y) = end; val mergeSort = fn : int list -> int list - mergeSort [4,3,2,1]; val it = [1,2,3,4] : int list - mergeSort [4,2,3,1,5,3,6]; val it = [1,2,3,3,4,5,6] : int list here 7/2/2018 IT 327

25 val (x, y) = halve theList in merge(mergeSort x, mergeSort y) end;
fun mergeSort nil = nil | mergeSort [e] = [e] | mergeSort theList = let (* fun and var defined locally *) fun halve nil = (nil, nil) | halve [a] = ([a], nil) | halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end; fun merge (nil, ys) = ys | merge (xs, nil) = xs | merge (x::xs, y::ys) = if (x < y) then x :: merge(xs, y::ys) else y :: merge(x::xs, ys); val (x, y) = halve theList in merge(mergeSort x, mergeSort y) end; 7/2/2018 IT 327

26 Quick Sort < < < < < < < < < < < <
7 5 8 14 6 1 16 2 11 10 9 13 3 15 12 4 < 7 5 8 4 6 1 3 2 11 10 9 13 16 15 12 14 < < < 2 3 1 4 6 8 5 7 11 10 9 12 16 15 13 14 < < < < < < < 2 1 3 4 6 5 8 7 9 10 11 12 14 13 15 16 < < < < < < < < < < < < < < < 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 7/2/2018 IT 327

27 pivot Quick Sort 7 5 8 14 6 1 16 2 11 10 9 13 3 15 12 4 4 3 2 16 14 8 2 5 4 3 6 1 7 16 11 10 9 13 14 15 12 8 1 2 4 3 6 5 7 8 11 10 9 13 14 15 12 16 1 2 3 4 6 5 7 8 11 10 9 13 14 15 12 16 1 2 3 4 5 6 7 8 9 10 11 13 14 15 12 16 1 2 3 4 5 6 7 8 9 10 11 12 13 15 14 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Using imperative PL’s, we have to explicitly implement these iterations. 7/2/2018 IT 327

28 Quick Sort in Java We have to explicitly implement these iterations.
private void SwapTwo(int A[], int i, int j){ int temp = A[i]; A[i]=A[j]; A[j]=temp; } public void QuickSort(int A[], int h, int t){ if (h == t) return; int i=h+1, j=t; if (i==j) { if (A[h] > A[i]) SwapTwo(A,h,i); return; while (i < j) { while (A[h] >= A[i] && i < t) i++; while (A[h] <= A[j] && j > h) j--; if (i < j) SwapTwo(A,i++,j--); if (i==j && A[h]>A[i]) SwapTwo(A,h,i); QuickSort(A,h,i-1); QuickSort(A,i,t); Quick Sort in Java We have to explicitly implement these iterations. 7/2/2018 IT 327

29 Quick Sort in ML pivot Anything wrong? How about split [2,2] ?
fun split nil = (nil,nil) | split [a] = ([a],nil) | split (a::b::tail) = let val (x,y) = split (a::tail) in if (a < b) then (x, b::y) else (b::x, y) end; fun quicksort nil = nil | quicksort [a] = [a] | quicksort a = val (x,y) = split a pivot This is more conceptual to the understanding of the problem Anything wrong? How about split [2,2] ? 7/2/2018 IT 327

30 Quick Sort in ML Force to split when there are two elements.
fun split nil = (nil,nil) | split [a] = ([a],nil) | split [a,b] = if (a <= b) then ([a],[b]) else ([b],[a]) | split (a::b::c) = let val (x,y) = split (a::c) in if (a < b) then (x, b::y) else (b::x, y) end; fun quicksort nil = nil | quicksort [a] = [a] | quicksort a = val (x,y) = split a Force to split when there are two elements. 7/2/2018 IT 327

31 Exercise Chapter 7.  Exercise: 2, 3, 5, 7, 8, 9, 10 7/2/2018 IT 327


Download ppt "ML Again ( Chapter 7) Patterns Local variable definitions"

Similar presentations


Ads by Google