Download presentation

Presentation is loading. Please wait.

1
**Programming with Lists**

cs776 (Prasad) L5lists

2
**Lists E.g., (true, [fn i:int => "i"])**

a is a type a list is a type (* Homogeneous lists. *) E.g., (true, [fn i:int => "i"]) : bool * (int -> string) list. E.g., [1, 2 , 3], 1::2::3::[] : int list; E.g., (op ::) : ’a * ’a list ->’a list; List constructors [] and :: can be used in patterns. Type constructor. Infix to prefix operator Functions => constructors. bool * (int -> string) list = bool * ( (int -> string) list ) cs776 (Prasad) L5lists

3
**Built-in operations on lists**

hd : ’a list -> ’a tl : ’a list -> ’a list null: ’a list -> bool : ’a list * ’a list -> ’a list (* append operation; infix operator *) length : ’a list -> int (* sets vs lists -- multiplicity; ordering *) cs776 (Prasad) L5lists

4
**Catalog of List functions**

init [1,2,3] = [1,2] last [1,2,3] = 3 Specs: init (xs @ [x]) = xs last [x]) = x Definitions: fun init (x::[]) = [] | init (x::xs) = x :: init xs; fun last (x::[]) = x | last (x::xs) = last xs; Illustrates recursive definitions. Spec describes the intent and is a consequence of the definition. Declarative specs vs Constructive definitions. Readability and correctness considerations for using list functions. Init and last are complementary to car-cdr. Non-exhaustive pattern generates warnings about “incompleteness”. Overlapping patterns are allowed because the rules are ordered. cs776 (Prasad) L5lists

5
**Definition: fun take 0 xs = [] take 3 [1,2,3,4] = [1,2,3]**

drop 2 [1,2,3] = [3] Definition: fun take 0 xs = [] | take n [] = [] | take n (x::xs) = x::take (n-1) xs; fun drop 0 xs = xs | drop n [] = [] | drop n (x::xs) = drop (n-1) xs; Takes or drops an initial segment Completeness and pattern matching. Signature enables discarding non-list arguments by the type checker. (Cf. Prolog where the corresponding first rule might succeed with args (0,anything)) Ensure completeness for list patterns. In general, the requirement that the first argument must be non-negative integer can be expressed either using an user-defined exception or by letting ML system catch it when the negative value creates trouble (such as inifinite loop). In this specific case, as the computation bottoms out for the empty list. Exception is the appropriate mechanism because n < 0 can be thought of as pre-condition violation by the caller. cs776 (Prasad) L5lists

6
**Definition: fun takewhile p [] = [] takewhile even [2,4,1,6,2] = [2,4]**

dropwhile even [2,3,8] = [3,8] Definition: fun takewhile p [] = [] | takewhile p (x::xs) = if p x then x :: takewhile p xs else []; fun dropwhile p [] = [] | dropwhile p (x::xs) = then dropwhile p xs else x::xs; Takes or drops an initial segment conditionally. Conditional expression: Observe that both THEN and ELSE clauses necessary. Also for conditional expression to be well-typed, both parts must have the same type or we can determine their least-upper-bound. Higher-order functions. The use of (p x) in the condition enables type inference engine to determine that p is a predicate. cs776 (Prasad) L5lists

7
**Role of patterns Signatures For testing type (“discrimination”)**

For picking sub-expressions apart Signatures take, drop : int -> ’a list -> ’a list takewhile, dropwhile : (’a -> bool) -> ’a list -> ’a list List.take, List.drop : ’a list * int -> ’a list Alternative to separate null?, car, cdr, etc in LISP/Scheme. List.take and List.drop are SML built-ins with the given signature. cs776 (Prasad) L5lists

8
**Selectors #i (a1,…, ai, …, an) = ai nth ([a0,…,ai,…,an],i) = ai**

Type of #i cannot be described in ML. List.nth : ’a list * int -> ’a fun nth (x::xs, 0) = x | nth (x::xs, i) = nth (xs, i-1) (* Patterns not exhaustive. Exception raised for null list input. *) Cartesian product – fixed arity. Non-exhaustive patterns cause ML Warnings. If you ignore, you are implicitly stating a precondition. ML is robust, so it will catch any violations downstream. To make this code robust, we need to add a user-defined exception for the empty-list case or negative args. cs776 (Prasad) L5lists

9
**filter : (’a -> bool) -> ’a list -> ’a list**

fun filter p [] = [] | filter p (x::xs) = if p x then x::filter p xs else filter p xs filter : (’a -> bool) -> ’a list -> ’a list Scans the entire list as opposed to the initial segment. cs776 (Prasad) L5lists

10
**(p x) orelse (exists p xs) **

fun exists p [] = false | exists p (x::xs) = (p x) orelse (exists p xs) exists : (’a -> bool) -> ’a list -> bool fun all p [] = true | all p (x::xs) = (p x) andalso (all p xs) all : (’a -> bool) -> ’a list -> bool Note the initialization for the empty-list case. Identity wrt boolean op. cs776 (Prasad) L5lists

11
**| pair (x::xs) (y::ys) = (x,y) :: pair xs ys ; **

fun pair [] ys = [] | pair (x::xs) [] = [] | pair (x::xs) (y::ys) = (x,y) :: pair xs ys ; pair: ’a list -> ’b list ->(’a * ’b) list exception error; fun zip f (x::xs) (y::ys) = (f x y) :: zip f xs ys | zip f [] [] = [] | zip f xs ys = raise error; zip : (’a -> ’b -> ’c ) -> ’a list -> ’b list -> ’c list Pair accepts lists of any length and uses the initial segment of the longer list that has the same length as the shorter list. Pairs corresponding elements in the list (cf. cartesian product) Zip generalizes pair and expects the two lists to be of the same length. If the input does not satisfy this, exception is raised at run-time. Resembles map for binary functions. Notice the generality captured by the signature. Even though patterns can be overlapping, ML orders clauses from top to bottom, thereby giving preference to earlier definition. The ordering of clauses in zip contributes to efficiency because non-empty lists are more likely inputs than the empty cases. cs776 (Prasad) L5lists

12
**Module List - open List; opening List**

datatype 'a list = :: of 'a * 'a list | nil exception Empty val null : 'a list -> bool val hd : 'a list -> 'a val tl : 'a list -> 'a list val last : 'a list -> 'a val getItem : 'a list -> ('a * 'a list) option val nth : 'a list * int -> 'a val take : 'a list * int -> 'a list val drop : 'a list * int -> 'a list val length : 'a list -> int val rev : 'a list -> 'a list … cs776 (Prasad) L5lists

13
**val concat : 'a list list -> 'a list **

… : 'a list * 'a list -> 'a list val concat : 'a list list -> 'a list val revAppend : 'a list * 'a list -> 'a list val app : ('a -> unit) -> 'a list -> unit val map : ('a -> 'b) -> 'a list -> 'b list val mapPartial : ('a -> 'b option) -> 'a list -> 'b list val find : ('a -> bool) -> 'a list -> 'a option val filter : ('a -> bool) -> 'a list -> 'a list val partition : ('a -> bool) -> 'a list -> 'a list * 'a list val foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b val exists : ('a -> bool) -> 'a list -> bool val all : ('a -> bool) -> 'a list -> bool val tabulate : int * (int -> 'a) -> 'a list - … cs776 (Prasad) L5lists

14
**Properties of functions**

Semantic Equivalence Efficiency Transformations Formal verification ; Debugging tool map f (map g x) = map (f o g) x all p (filter p x) = true (map f) o (filter (p o f)) = (filter p) o (map f) John Backus’s Turing Award Lecture : Define Algebra of programs (identities) -- Suitable for formal manipulation and reasoning about programs. HOF improve Readability through modular construction of programs. Efficiency obtained thro automatic translation. Reliability/Correctness through formal equational reasoning. Code naturally. Pattern directed optimization by orienting identities to improve space/time requirements. cs776 (Prasad) L5lists

15
**Modular Designs using Lists**

Abstraction and Reuse Ref: Structure and Interpretation of Computer Programs (Abelson and Sussman) Meyer’s Criteria for Modular Design Methodology 1. Decomposability (independence) 2. Composability (reuse) 3. Continuity (independence) 4. Understandability 5. Protection cs776 (Prasad) L5lists

16
**(define (sum-odd-squares tree) (cond ((null? tree) 0) ((pair? tree) **

(+ (sum-odd-squares (car tree)) (sum-odd-squares (cdr tree)) ) (else (if (odd? tree) (* tree tree) 0)) )) Takes a tree and computes the sum of the squares of the leaves that are odd. Retained Scheme syntax because of heterogeneity. cs776 (Prasad) L5lists

17
(define (even-fibs n) (define (next k) (if (> k n) ’( ) (let ((f (fib k)) (if (even? f) (cons f (next (+ k 1))) (next (+ k 1)) )) )) (next 0)) Takes a number n and constructs a list of even numbers from among the first n Fibonacci numbers. cs776 (Prasad) L5lists

18
**Abstract Descriptions**

enumerates the leaves of a tree filters them, selecting the odd ones squares each of the selected ones accumulates the results using +, starting with 0 enumerates the integers from 0 to n computes the Fibonacci number for each integer filters them, selecting the even ones accumulates the results using cons, starting with () Instead of using two dissimilar customized recursive definitions for the two problems, understand their similarities, and exploit it by defining and reusing common primitives. cs776 (Prasad) L5lists

19
**(define (filter pred seq) (cond ((null? seq) ( )) ((pred (car seq)) **

(cons (car seq) (filter pred (cdr seq)))) (else (filter pred (cdr seq))) )) (define (accumulate op init seq) (if (null? seq) init (op (car seq) (accumulate op init (cdr seq))) Typically, init and op in accumulate are connected. init op x = x op init = x cs776 (Prasad) L5lists

20
**(define (enum-interval low high) (if (> low high) ( ) **

(cons low (enum-interval (+ low 1) high)) )) (define (enum-tree tree) (if ((null? tree) ( )) ((pair? tree) (append (enum-tree (car tree)) (enum-tree (cdr tree)) )) (else (list tree)))) cs776 (Prasad) L5lists

21
**(define (sum-odd-squares tree) (accumulate + 0 **

(map (lambda (x) (* x x)) (filter odd? (enum-tree tree))))) (define (even-fibs n) (accumulate cons nil (filter even? (map fib (enum-interval 0 n))))) In even-fibs, the final accumulate is unnecessary. cs776 (Prasad) L5lists

22
**Generality (define (list-fib-squares n) (map square (map fib**

(enum-interval 0 n) )) ) (define (highest-salary-of-programmer records) (accumulate max 0 (map salary (filter programmer? records)))) Modular – Reuse (applied to different context) Combine reusable blocks a different way and then for a different problem. Explicitly write only what is application specific. cs776 (Prasad) L5lists

23
**Inefficiencies Find the fifth prime in the interval 100 to 1000**

(caddddr (filter prime? (enum-interval )) Sum all primes between x and y (define (sum-prime x y) (accumulate + 0 (filter prime? (enum-interval x y)))) Large list constructed even though a small initial segment is needed. Non-incremental (see alternative in the next overhead). A lot of work into how to take such definitions and execute in an interleaved fashion for efficiency. (cf. Prolog) cs776 (Prasad) L5lists

24
**Rewrite (define (sum-prime x y) (define (iter count accum)**

(if (> count y) accum (if (prime? count) (iter (+ 1 count) (+ accum count)) (iter (+ 1 count) accum) ))) (iter x 0)) Does not construct the large list at one time. Incrementally checks each element instead. (Tail recursion) cs776 (Prasad) L5lists

Similar presentations

Presentation is loading. Please wait....

OK

© 2004 Goodrich, Tamassia Node-Lists1 6.2 Node Lists.

© 2004 Goodrich, Tamassia Node-Lists1 6.2 Node Lists.

© 2018 SlidePlayer.com Inc.

All rights reserved.

To make this website work, we log user data and share it with processors. To use this website, you must agree to our Privacy Policy, including cookie policy.

Ads by Google