1 / 31

Patterns Local variable definitions Two sorting examples

ML Again ( Chapter 7). Patterns Local variable definitions Two sorting examples. The implementation using functional languages is closer to the concepts of the solutions. Both n and ( a,b ) are patterns. fun f n = n*n; fun g (a,b) = a*b;. n is a pattern of integers;

zandra
Download Presentation

Patterns Local variable definitions Two sorting examples

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

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. IT 327

  2. Both n and (a,b) are patterns. • fun f n = n*n; • fun g (a,b) = a*b; 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

  3. Underscore is a Pattern - fun f _ = "yes"; val f = fn : 'a -> string - f 34.5; val it = "yes" : string - f []; val it = "yes" : string • The underscore matches anything, but does not bind it to a variable fun f x = "yes"; 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"; 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 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? 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 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 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 IT 327

  10. Syntax <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 IT 327

  11. Overlapping Patterns - 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 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 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 L) @ [hd L]; fun reverse nil = nil | reverse (first::rest) = reverse rest@[first]; IT 327

  14. A Restriction How to explain this? fun f (a,a) = … | f (a,b) = … This is not legal, but why? fun f (a,b) = if (a=b) then … else … 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 a = 1 : int val b = [2,3,4,5] : int list 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 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 * 1000.0 end; IT 327

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

  19. Merge Sort IT 327

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

  21. halve fun halve nil = (nil, nil) | halve [a] = ([a], nil) | halve (a::b::cs) = let val (x, y) = halvecs 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 IT 327

  22. Recursively merge 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); IT 327

  23. Merge Sort 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, 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 IT 327

  25. 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 theListin merge(mergeSort x, mergeSort y)end; IT 327

  26. Quick Sort < < < < < < < < < < < < < < < < < < < < < < < < < < IT 327

  27. pivot Quick Sort 4 3 2 16 14 8 Using imperative PL’s, we have to explicitly implement these iterations. IT 327

  28. 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. IT 327

  29. Quick Sort in ML 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 = let val (x,y) = split a in quicksort(x)@quicksort(y) end; pivot This is more conceptual to the understanding of the problem Anything wrong? How about split [2,2] ? IT 327

  30. Quick Sort in ML 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 = let val (x,y) = split a in quicksort(x)@quicksort(y) end; Force to split when there are two elements. IT 327

  31. Homework 3 Chapter 7.  Exercise: 2, 3, 5, 7, 8, 9, 10 Due Oct 17. IT 327

More Related