Presentation is loading. Please wait.

Presentation is loading. Please wait.

review, let and lambda, trees?, tree-recursion?, OCAML intro

Similar presentations


Presentation on theme: "review, let and lambda, trees?, tree-recursion?, OCAML intro"— Presentation transcript:

1 review, let and lambda, trees?, tree-recursion?, OCAML intro
Class 17 review, let and lambda, trees?, tree-recursion?, OCAML intro

2 Midsemester Review Using the design recipe to write programs
Recursion is very powerful Helpers can simplify your programs Tests can save you development time Solving a more general problem may be easier than solving a less general one In code, this often translates to "adding an extra argument" (e.g. fancy-censor) Having simple representations of structure (like lists or trees) makes it easy to write programs that work with these representations We can analyze procedures and determine their big-O class

3 Why is solving a more general problem sometimes easier?
When we solve a reduced problem (i.e., get a recursive result), that solution, for the simple problem, may not be as useful as the same kind of result for the general problem. In fancy-censor, our naïve recursion produced, as a recursive result, a censored-list starting with "*"; to make it useful to us, we might have to go through and replace all "*" with "+" and vice-versa Our improved version of fancy-censor solved a more general problem: censor a list with an alternating sequence of "*" and "+", starting with whichever one we specify. This meant that we could get back something more general from the recursive call, and produce the overall answer more simply.

4 Limits on lambda We cannot seem to write a recursive procedure using lambda (let ((len (lambda (alod) (cond [(empty? alod) 0] [(cons? alod) (+ 1 (len (rest alod)))])))) (len (list 1 2 3))) Inner "len" cannot refer to outer one (see the rules of evaluation)

5 A solution (letrec ((len (lambda (alod) (cond [(empty? alod) 0]
[(cons? alod) (+ 1 (len (rest alod)))])))) (len (list 1 2 3))) => 3

6 Use map2 to write map You've got, say, an int -> bool function you'd like to apply to each item in an int list (e.g., odd?, (list 1 2 5) ). You have a procedure that expects two lists wants a procedure that takes two arguments, to apply pairwise Two lists? Why not just use your single list twice. Then apply your proc to just the first of the two arguments (define (map p alod) (map2 p alod alod)) Doesn't work – p is a one-argument procedure! (define (map p alod) (map2 (lambda (x y) (p x)) alod alod)) You really need to use lambda to do this sort of thing, because you need to create a new procedure, and that is lambda's job!

7 Trees

8 Trees model "parent-child" relations
"expression trees": 'draw' (3+4) * (2 - 1/6) as * + - 3 4 2 / 1 6

9 Trees model "parent-child" relations
Folder/file structures Desktop CS17 ADMIN Lec01.ppt NOTES YuRec.doc Staffing.txt Lec01.ppt

10 Trees model "parent-child" relations
Hierarchy (President is the boss of provost and Vice Pres for research; provost is the boss of …) Classification: life forms divides into Kingdoms, each divided into Phylums, each divided into Orders, etc. Recursive procedure invocation Nodes contain expressions Each recursive evaluation placed in a child node

11 Tree terminology Root: top of the tree Node: something with children
Leaf: something without children Parent: the node connected above you Child: the opposite Sibling: have same parent Ancestor: anyone between you and the root, including root. Descendant: you can guess this Depth: for a tree consisting of a single leaf: 0. For any other: 1 + max(depth(children)). This example: Depth = 2. Binary tree: each internal node has 2 children ROOT LEAF NODE LEAF LEAF

12 Minor debate: do all points of a tree contain data, or do leaves not contain data?
* * + - + - 3 4 2 / 3 4 2 / 6 1 6 1 To make recursion easier, we choose the "empty leaves" model in CS17

13 Representing trees in Racket, version 1
(Briefly) Break a CS rule: use mixed data in lists! A tree with a node containing 7, and left and right subtrees both being leaves, is represented by (list 7 empty empty) More generally empty represents a leaf Nodes are written (list node-val left-subtree right-subtree)

14 Trees in Racket, v1, continued
To abstract this representation, we write a data definition: ;; an 'a tree is either ;; a leaf or ;; a node, consisting of ;; a value, of type 'a, and ;; two 'subtrees', each of type 'a tree, the "left" and the "right" ;; nothing else is an 'a tree. ;; ;; We represent a leaf by the empty list, and ;; the node with value v, left-subtree t1, and right-subtree t2, by ;; (list v t1 t2)

15 Trees in Racket, v1, continued
To fill in the abstraction we write a few procs: ;; left-subtree: 'a node -> 'a tree (define (left-subtree n) (first (rest n))) ;; right-subtree: 'a node -> 'a tree (define (right-subtree n) (first (rest (rest n)))) ;; node-val: 'a node -> 'a (define (node-val n) (first n)) ;; make-node: 'a * 'a tree* 'a tree -> 'a node (define (make-node val left right) (list val left right)) ;; make-leaf: . -> 'a tree (define (make-leaf ) empty) ;; leaf?: 'a tree -> bool (define leaf? empty?) ;; node?: 'a tree -> bool (define node? cons?)

16 Details on "node?" ;; node? ;; node?: tree -> bool ;; input: a tree, t, that may be a node or a leaf ;; output: true, if t is a node, false if it's a leaf (define node? cons?)

17 depth of a tree ;; depth: 'a tree -> int ;; input: t, an 'a tree ;; output: the depth of t, where the depth of a leaf is defined to be 0. (define (depth t) (cond [(leaf? t) ...] [(node? t) ... (node-val t) (left-subtree t) (right-subtree t)..]))

18 depth of a tree ;; depth: 'a tree -> int ;; input: t, an 'a tree ;; output: the depth of t, where the depth of a leaf is defined to be 0. (define (depth t) (cond [(leaf? t) 0] [(node? t) ... (node-val t) (left-subtree t) (right-subtree t)..]))

19 depth of a tree ;; depth: 'a tree -> int ;; input: t, an 'a tree ;; output: the depth of t, where the depth of a leaf is defined to be 0. (define (depth t) (cond [(leaf? t) 0] [(node? t) (+ 1 (max (depth (left-subtree t)) (depth (right-subtree t))))]))

20 Using this as a guide, write tcontains17
Using this as a guide, write tcontains17?, a procedure that searches an int tree to say whether it contains the number 17. ;; depth: 'a tree -> int ;; input: t, an 'a tree ;; output: the depth of t, where the depth of a leaf is defined to be 0. (define (depth t) (cond [(leaf? t) 0] [(node? t) (+ 1 (max (depth (left-subtree t)) (depth (right-subtree t))))]))

21 tcontains17? ;; tcontains17?: int tree -> bool ;; input: t, an int tree ;; output: true if the value at some node of t is 17; false otherwise (define (tcontains17? t) (cond [(leaf? t) false] [(node? t) (or (= 17 (node-val t)) (tcontains17? (left-subtree t)) (tcontains17? (right-subtree t)))]))

22 Can we do this in a way that doesn't abuse our rule about homogeneous lists?
We can, using racket "structs" (i.e., structures) We won't actually use these in CS17, because OCaml provides something much nicer for doing this (i.e., doing this is more natural in OCaml) General lesson: Different languages suit different tasks better.

23 tcontains17? runtime Let T(d) be the number of elem.
(define (depth t) (cond [(leaf? t) false] [(node? t) (or (= 17 (node-val t)) (tcontains17? (left-subtree t)) (tcontains17? (right-subtree t)))])) tcontains17? runtime Let T(d) be the number of elem. operations involved in evaluating (tcontains17? t) on any tree of depth d. Why not "containing n nodes?" We could do that instead What's the recurrence? 𝑇 0 =𝐴 𝑇 𝑑 ≤𝐵+2𝑇 𝑑−1 Solution: 𝑇 𝑑 ≤ 𝐶⋅2 𝑑 for some constant 𝐶. [Takes proof.], so 𝑇∈𝑂( 2 𝑑 ) If we'd done analysis in terms of 𝑛, we'd have gotten a bad overestimate Need improved method, which we'll see later.

24 Ocaml

25 Very much like Racket in some ways
A functional programming language, i.e., functions are first-class entities in the language Makes heavy use of lists Recursion is very natural Many procedures begin with a cond-like structure Differences types are very much part of the language, rather than something you just put in the comments Arithmetic is "infix", i.e., we write instead of (+ 3 2) In addition to lists, we have "tuples"

26 CS17 Ocaml As with Racket, we'll only work with a small part of Ocaml

27 OCaml characteristics
There’s almost a dictionary to translate from Racket into Ocaml Less structure in page-layout of programs No “DrOCaml”  Still has an ‘interactive’ mode where you can type things and see them evaluated

28 Key differences Ocaml has a notion of “types” and is very rigid about them. This will annoy you at first, but soon you’ll love it Make debugging easier (after the first few days) Ocaml has “cond on steroids”, called “pattern matching” Effectively does “cond” and a “let” that extracts all the parts (like “first” and “rest”) for you and names them all at once. Ocaml has struct-like types built in, in a very simple form Ocaml has variant types (like “a season is Fall or Winter or …”) built in Ocaml has recursive type (like “lists”) both built in and easy to create “lambda” is called “fun” All functions take one argument, sort of. Expressions end with semicolons (which also get used elsewhere!)

29 Basic types int, float, string, bool
int constants have no decimal; float constants have a decimal > 4 4: int > 4. 4.0: float

30 Do types matter? Yes! You must indicate types when you’re coding…
…and Ocaml, when it runs, checks that they all make sense or it halts You cannot make a list like (list 3 4 true) in Ocaml, because its type-system allows only monotype lists. (Racket allowed mixed lists, but CS17 didn’t…to prepare you for Ocaml!) Some error checks are done for you, so you never need to write code that checks wither the arg is a string or not, and if not, gives an error!

31 Remainder of class: learning to translate!

32 Ocaml code

33 # 3 + 5;; -: int = 8 # ;; - : float = 5.5 +, -, *, / (for ints) +., -., *., /. (for floats) # 2.0 ** 4.0;; : float = 16. # float_of_int(16);; -: float = 16. ceil, floor, ???...but int_of_float might help.

34 4 > > == 5

35 # ;; -: int = 16 The “-” means “the value you just computed doesn’t have a name (or identifier) associated to it. The “:” always comes between a thing and its type, so the value we computed is an “int” The actual value of that int is 16

36 &&, ||, not, true, false (4 > 2) && (3 == 3) or 4 > 2 && 3 == 3 because == and < “bind tighter” than && (15 < 16) && (17.0 < 18.0) OK because both subexps evaluate to bools “abc” ^ “def” [3;4]

37 let x = 5;; let f(x) = x + 1;; let f x = x + 1;; let f(x:int):int = x + 1;; CS17 approved form let f (x:int) (y:int):int = x + y;;

38 if 3 < 5 then “eleven” else 4 fail: expression has
if 3 < 5 then 11 else 2 + 8 if 3 < 5 then “eleven” else 4 fail: expression has a type, just as do its pieces. Is this str or int? NB: Ocaml if-expressions are expressions with values, just as if- expressions are in Racket Don’t be fooled by their looking like “statements”.

39 Tuples: low-budget combinations of data
Mixed data types OK Fixed size: you can’t ‘cons onto a tuple’ No such thing as a 1-tuple. Selectors, type-predicates? See pattern matching. <expr>,<expr> is a tuple. “,” is an operator, like +! Almost always in parens, as in # (3, 5);; -: int * int: (3, 5) # 3, 5;; -: int * int: (3, 5) parens optional, but really nice # (3, “hello”, true);; -: int * string * bool = (3, “hello”, true) “,” is the constructor for all tuples!

40 [] brackets are used for ocaml lists 17 :: [] “::” is read “cons” [2 ; 3 ; 5] “;” is used to separate items in a list # [3;4;5];; - : int list = [3; 4; 5] note: int list! monomorphic

41 Writing a recursive procedure
# let rec myLen (lst: 'a list):int = match lst with | [] -> 0 | hd::tl -> 1 + myLen tl;; match…with is the new "cond" | is used to indicate various cases -> is used to separate the case-selection from the associated value Some clever name-assignment goes on too

42

43 type shape = Circle of float | Rectangle of float * float
The capital letters are essential: all named constructors begin with those! Type-names, by contrast, must start lower-case. Simplest form: type season = | Fall the “|” is read “or” | Winter extra “|” at front allowed for neatness | Spring | Summer

44 # type card = | Clubs of int | Spades of int | Diamonds of int | Hearts of int;; type card = Clubs of int | Spades of int | Diamonds of int | Hearts of int # let rank (c:card) : int = match c with | Clubs n -> n | Diamonds n -> n | Hearts n -> n | Spades n -> n;; val rank : card -> int = <fun> # Hearts 4;; Note that “of” appears in type definition, but NOT in use of constructor : card = Hearts 4 # rank (Hearts 4);; : int = 4

45

46 A few last ideas from analysis

47 Comparing functions 𝑓∈O 𝑔 means that 𝑓 is eventually less than 𝑔, up to constants. For list-procedures, if the op-counting function 𝑓∈𝑂(𝑛↦𝑛), we're generally pretty happy; we say that the procedure runs in at most linear time. There's a way to characterize a comparison in the other direction: if 𝑓 is eventually less than 𝑔, up to constants, we say that 𝑔∈Ω 𝑓 . Ω(𝑓) is defined to be the set of all functions 𝑔 with the property that 𝑓 is eventually less than 𝑔, up to constants. Very informally: Ω(𝑓) consists of functions "that grow at least as fast as 𝑓"

48 A combination The set Θ(𝑓) consists of functions 𝑔 with the properties that 𝑓 is eventually less than 𝑔, up to constants, and 𝑔 is eventually less than 𝑓, up to constants Again informally: Θ(𝑓) consists of functions that "grow the same way as 𝑓" When we looked at the op-counter, 𝐿, for the length procedure, we found that 𝐿 0 =𝐴 𝐿 𝑛 =𝐵+𝐿 𝑛−1 for 𝑛>0 and via plug-n-chug, arrived at the (correct) conjecture that 𝐿 𝑛 =𝐵𝑛+𝐴.

49 𝐿 𝑛 =𝐵𝑛+𝐴 where 𝐴, 𝐵>0. It's not hard to see that 𝐿∈𝑂(𝑛↦𝑛); an 𝑀,𝑐 -proof uses 𝑀= 1, 𝑐=𝐴+𝐵. It's also true that the function 𝑛↦𝑛 is in 𝑂(𝐿); use 𝑀=1, 𝑐= 1 𝐵 . Hence the runtime of the length procedure is in Θ(𝑛↦𝑛), and we can say that length is not merely "at worst linear time", but is in fact "linear time". Sadly, many CS folks say "such-and-such is 𝑂(𝑛↦ 𝑛 2 )" to mean that it's Θ(𝑛↦ 𝑛 2 ), for instance, conflating big-O and big=Theta classes

50 Boxes and pointers: a model for lists in memory

51 Bignum solution


Download ppt "review, let and lambda, trees?, tree-recursion?, OCAML intro"

Similar presentations


Ads by Google