Tuples Another Example

Tuples Another Example

Tuples CMSC 330: Organization of Constructed using (e1, ..., en) Programming Languages Deconstructed using pattern matching • Patterns involve parens and commas, e.g., (p1,p2, …) Tuples are like C structs • But without field labels OCaml 2 • Allocated on the heap Higher Order Functions Tuples can be heterogenous • Unlike lists, which must be homogenous • (1, ["string1"; "string2"]) is a valid tuple CMSC 330 - Spr ing 2016 1 CMSC 330 - Spr ing 2016 2 Examples With Tuples Another Example let plusThree (x, y, z) = x + y + z let addOne (x, y, z) = (x+1, y+1, z+1) let f l = match l with x::(_::y) -> (x,y) • plusThree (addOne (3, 4, 5)) (* returns 15 *) What is f [1;2;3;4]? Possibilities: ([1],[3]) let sum ((a, b), c) = (a+c, b+c) • sum ((1, 2), 3) = (4, 5) (1,3) (1,[3]) let plusFirstTwo (x::y::_, a) = (x + a, y + a) (1,4) • plusFirstTwo ([1; 2; 3], 4) = (5, 6) (1,[3;4]) let tls (_::xs, _::ys) = (xs, ys) • tls ([1; 2; 3], [4; 5; 6; 7]) = ([2; 3], [5; 6; 7]) Remember, semicolon for lists, comma for tuples • [1, 2] = [(1, 2)] = a list of size one • (1; 2) = Warning: This expression should have type unit CMSC 330 - Spr ing 2016 3 CMSC 330 - Spr ing 2016 4 1 List And Tuple Types List And Tuple Types Tuple types use * to separate components Tuple types use * to separate components Examples Examples • (1, 2) : • (1, 2) : int * int • (1, "string", 3.5) : • (1, "string", 3.5) : int * string * float • (1, ["a"; "b"], 'c') : • (1, ["a"; "b"], 'c') : int * string list * char • [(1,2)] : • [(1,2)] : (int * int) list • [(1, 2); (3, 4)] : • [(1, 2); (3, 4)] : (int * int) list • [(1,2); (1,2,3)] : • [(1,2); (1,2,3)] : error Ø Because the first list element has type int * int, but the second has type int * int * int – list elements must all be of the same type CMSC 330 - Spr ing 2016 5 CMSC 330 - Spr ing 2016 6 Polymorphic Types Examples Of Polymorphic Types Some functions we saw require specific list types let tl (_::t) = t • let plusFirstTwo (x::y::_, a) = (x + a, y + a) • tl : 'a list -> 'a list • plusFirstTwo : int list * int -> (int * int) let swap (x, y) = (y, x) But other functions work for any list • swap : 'a * 'b -> 'b * 'a • let hd (h::_) = h • hd [1; 2; 3] (* returns 1 *) let tls (_::xs, _::ys) = (xs, ys) • hd ["a"; "b"; "c"] (* returns "a" *) • tls : 'a list * 'b list -> 'a list * 'b list OCaml gives such functions polymorphic types • hd : 'a list -> 'a let eq (x,y) = x = y • this says the function takes a list of any element type • eq : 'a * ’a -> bool 'a, and returns something of that type CMSC 330 - Spr ing 2016 7 CMSC 330 - Spr ing 2016 8 2 Tuples Are A Fixed Size Conditionals This OCaml definition Use if...then...else like C/Java/Ruby • # let foo x = match x with • But no parentheses, no elsif, and no end (a, b) -> a + b if grade >= 90 then | (a, b, c) -> a + b + c;; print_string "You got an A" else if grade >= 80 then Would yield this error message print_string "You got a B" • This pattern matches values of type 'a * 'b * 'c else if grade >= 70 then but is here used to match values of type 'd * 'e print_string "You got a C" else print_string "You’re not doing so well" Tuples of different size have different types • Thus never more than one match case with tuples CMSC 330 - Spr ing 2016 9 CMSC 330 - Spr ing 2016 10 Conditionals (cont.) The Factorial Function In OCaml, conditionals return a result Using conditionals & functions • The value of whichever branch is true/false • Can you write fact, the factorial function? • Like ? : in C, C++, and Java let rec fact n = # if 7 > 42 then "hello" else “goodbye";; if n = 0 then - : string = "goodbye" 1 # let x = if true then 3 else 4;; else n * fact (n-1);; x : int = 3 # if false then 3 else 3.0;; This expression has type float but is Notice no return statements here used with type int • This is pretty much how it needs to be written CMSC 330 - Spr ing 2016 11 CMSC 330 - Spr ing 2016 12 3 Let Rec Let – More Examples The rec part means “define a recursive let f n = 10;; function” let f n = if n = 0 then 1 else n * f (n – 1);; Let vs. let rec • let x = e1 in e2 x in scope within e2 • f 0;; (* 1 *) • f 1;; • let rec x = e1 in e2 x in scope within e2 and e1 (* 10 *) Why use let rec? let f x = … f … in … f … If you used let instead of let rec to define fact • • (* Unbound value f *) let fact n = if n = 0 then 1 let rec f x = … f … in … f … else n * fact (n-1) in e2 • (* Bound value f *) Fact is not bound here! CMSC 330 - Spr ing 2016 13 CMSC 330 - Spr ing 2016 14 Recursion = Looping Lists and Recursion Recursion is essentially the only way to iterate Lists have a recursive structure • (The only way we’re going to talk about) • And so most functions over lists will be recursive let rec length l = match l with Another example [] -> 0 | (_::t) -> 1 + (length t) let rec print_up_to (n, m) = print_int n; print_string "\n"; if n < m then print_up_to (n + 1, m) • This is just like an inductive definition Ø The length of the empty list is zero Ø The length of a nonempty list is 1 plus the length of the tail • Type of length? CMSC 330 - Spr ing 2016 15 CMSC 330 - Spr ing 2016 16 4 More Examples More Examples (cont.) sum l (* sum of elts in l *) (* return a list containing all the elements in the let rec sum l = match l with list l followed by all the elements in list m *) [] -> 0 append (l, m) | (x::xs) -> x + (sum xs) let rec append (l, m) = match l with [] -> m negate l (* negate elements in list *) | (x::xs) -> x::(append (xs, m)) let rec negate l = match l with [] -> [] rev l (* reverse list; hint: use append *) | (x::xs) -> (-x) :: (negate xs) let rec rev l = match l with [] -> [] last l (* last element of l *) | (x::xs) -> append ((rev xs), [x]) let rec last l = match l with [x] -> x rev takes O(n2) time. Can you do better? | (x::xs) -> last xs CMSC 330 - Spr ing 2016 17 CMSC 330 - Spr ing 2016 18 A Clever Version of Reverse More Examples let rec rev_helper (l, a) = match l with flattenPairs l (* ('a * 'a) list -> 'a list *) [] -> a let rec flattenPairs l = match l with | (x::xs) -> rev_helper (xs, (x::a)) [] -> [] let rev l = rev_helper (l, []) | ((a, b)::t) -> a :: b :: (flattenPairs t) Let’s give it a try take (n, l) (* return first n elts of l *) let rec take (n, l) = rev [1; 2; 3] → if n = 0 then [] rev_helper ([1;2;3], []) → else match l with rev_helper ([2;3], [1]) → [] -> [] rev_helper ([3], [2;1]) → | (x::xs) -> x :: (take (n-1, xs)) rev_helper ([], [3;2;1]) → [3;2;1] CMSC 330 - Spr ing 2016 19 CMSC 330 - Spr ing 2016 20 5 Working With Lists Anonymous Functions Several of these examples have the same flavor Recall code blocks in Ruby • Walk through the list and do something to every (1..10).each { |x| print x } element • Here, we can think of { |x| print x } as a function • Walk through the list and keep track of something We can do this (and more) in Ocaml Recall the following example code from Ruby: range_each (1,10) (fun x -> print_int x) a = [1,2,3,4,5] b = a.collect { |x| -x } let rec range_each (i,j) f = • where if i > j then () • Here we passed a code block into the collect method else • Wouldn’t it be nice to do the same in OCaml? let _ = f i in (* ignore result *) range_each (i+1,j) f CMSC 330 - Spr ing 2016 21 CMSC 330 - Spr ing 2016 22 Anonymous Functions All Functions Are Anonymous Passing functions around is very common Functions are first-class, so you can bind them • So often we don’t want to bother to give them names to other names as you like let f x = x + 3 Use fun to make a function with no name let g = f Parameter Body g 5 = 8 In fact, let for functions is just shorthand fun x -> x + 3 let f x = body (fun x -> x + 3) 5 = 8 ↓ stands for let f = fun x -> body CMSC 330 - Spr ing 2016 23 CMSC 330 - Spr ing 2016 24 6 Examples Higher-Order Functions let next x = x + 1 In OCaml you can pass functions as arguments, • Short for let next = fun x -> x + 1 and return functions as results let plus (x, y) = x + y let plus_three x = x + 3 • Short for let plus = fun (x, y) -> x + y let twice f z = f (f z) twice plus_three 5 • Which is short for twice : ('a->'a) -> 'a -> 'a Ø let plus = fun z -> (match z with (x, y) -> x + y) let plus_four x = x + 4 let pick_fn n = let rec fact n = if n > 0 then plus_three else plus_four if n = 0 then 1 else n * fact (n-1) (pick_fn 5) 0 • Short for let rec fact = fun n -> pick_fn : int -> (int->int) (if n = 0 then 1 else n * fact (n-1)) CMSC 330 - Spr ing 2016 25 CMSC 330 - Spr ing 2016 26 Currying Curried Functions In OCaml We just saw a way for a function to take multiple OCaml has a really simple syntax for currying arguments let add x y = x + y • The function consumes one argument at a time, • This is identical to all of the following: returning a function that takes the rest let add = (fun x -> (fun y -> x + y)) let add = (fun x y -> x + y) let add x = (fun y -> x+y) This is called curryingthe function Thus: • Named after the logician Haskell B.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    10 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us