320 likes | 477 Views
Functional Programming COMP2003. A course on functional programming using Common Lisp Dr Eleni Mangina eleni.mangina@ucd.ie. Mapping And Iteration. So far, the only Lisp mechanism we have considered, which allows an action to be performed repeatedly is recursion.
E N D
Functional Programming COMP2003 A course on functional programming using Common Lisp Dr Eleni Mangina eleni.mangina@ucd.ie
Mapping And Iteration • So far, the only Lisp mechanism we have considered, which allows an action to be performed repeatedly is recursion. • Most programming languages also have non-recursive constructs which allow the programmer to specify that an action is to be repeated
Mapping Functions Mapping functions are used when: • The repetition is for each element (or subpart) of a list; • The computation to be done each time is easily expressible as a function • MAPC, MAPCAR
MAPC • The mapc function, takes a function, and applies that function to all the items in a list. • For example, to print all the items in the list returned by the computation (compute-list-of-numbs) all that is needed is: (mapc #’print (compute-list-of-numbs))
MAPC To print out all the items in the list listofvalues, each on a new line (where terpri outputs a new line), in between angle brackets: (mapc #’(lambda (x) (print “<“) (print x) (print “>“) (terpri) ) listofvalues )
MAPC • MAPC is used where the side-effect of the computation is required, but where the overall result of the computation is irrelevant. If the function given to MAPC needs more than one argument, then there should be as many lists of values supplied as it takes arguments: (mapc <function> <arguments-1><arguments-2>…<arguments-N>)
MAPC-for example: (mapc #’(lambda ( x y) (cond ((not (eql x y)) (print (list x y)))) ) ‘(4 6 7 11 2) ‘(3 6 7 10) ) (4 3) (11 10) Notice that if the lists are not all the same length, then the repetition terminates once the shortest list has been used up; the different lengths do not cause an error
MAPCAR • This function takes a function as an argument and applies it to all items of a given list, returning as a result a list of al the results thus obtained: (mapcar #’* ‘(2 3 4) ‘(5 6 7)) will produce the list: (10 18 28) (mapcar #’first (list ‘(a b) ‘(c d) ‘(e f))) will produce the result list (a c e) (mapcar #’+ (2 5 4) (10 11) (7 8 9 6)) (19 24)
> (remove-all ‘b ‘(a b c d b e f b)) (a c d e f) This can be done by: (defun remove-all (x list1) (mapcan #’(lambda (element) (cond ((eql x element) ()) (t (list element)) ) ) list1 ) )
EXAMPLE – EXERCISE: • Suppose you have a tree-node data type: ;; node-value: argument a list representing a node ;; returns associated value of a node (defun node-value (node) (first node)) ;; node-left: argument a list representing a node ;; returns left –daughter node if any (defun node-left (nd) (second nd)) ;; node-right: argument a list representing a node ;; returns right-daughter node if any (defun node-left (nd) (third nd))
EXAMPLE – EXERCISE (cont.): ;; terminal: argument item representing a node ;; returns T if no daughters (defun terminal (nd) (and (null (node-left nd)) (null (node-right nd))) ) ;; search-tree: arguments! 1. A node in a tree & ;; 2. An integer to be sought in the tree from that node downwards. ;; returns the sub tree which has that integer as its root (defun search-tree (tree target) (cond ((equal target (node-value tree)) tree) ; found it ((terminal tree) nil) ; run out of tree to search (t (or (search-tree (node-left tree) target) (search-tree (node-right tree) target)))))
EXAMPLE – EXERCISE (cont.): • How would you write a function GET-DAUGHTERS, which take one argument (a list of tree nodes) and returns a list of all the daughter-nodes of the given nodes, in the same left to right order? (defun get_daughters (list) (cond ((not (terminal list)) (apply #'append ((mapcar #'node-left list) (mapcar #'node-right list)))) ) )
EVERY This function returns a non-NIL result of the function supplied yields a non-NIL result on each element of the list > (every #’numberp ‘(2 5 3 6)) t > (every #’numberp ‘(2 hello 3 5)) nil > (every #’= ‘(2 4 6) (list ( - 3 1) (+ 2 2) (* 2 3))) t
SOME This function returns a non-NIL result if the function yields a non-NIL result on some element of the list (or lists). > (some #’numberp ‘(a b 3 4)) t > (some #’numberp ‘(hello and welcome)) nil > (some #’= ‘(3 4 5) (list (-3 1) (+2 2) (*2 3))) t
ITERATIVE CONSTRUCTS: DOLIST • A slightly different way of having a particular computation applied to all the elements of a list: > (dolist (x ‘(1 2 3 4 5 6) ‘t) (cond ((evenp x) (print x))) ) 2 4 6 t Here, X is the local variable, (1 2 3 4 5 6) is the list to be scanned, ‘t is the result of the expression; there is only one statement to be executed for each value of X
DOTIMES It allows the repetition of a computation a fixed number of times. Its arguments specify a local variable, a number of times for the repetition, a result expression and a sequence of Lisp expressions to be executed. The expressions are executed the given number of times, and each time the supplied variable has a different value > (dotimes (c 4 ‘done) (print (“Counter = “) (print c)) Counter = 0 Counter = 1 Counter = 2 Counter = 3 done
Example: (defun max-of-readings (limit) (let ((numb nil) (maxval nil)) (dotimes (n limit maxval) (setf numb (read)) (cond ((numberp maxval) (if (> numb maxval) (setf maxval numb))) (t (setf maxval numb)) ) ) ) )
LOOP The loop command takes no arguments, apart from the sequence of expressions which form the body of the iteration: (loop (let ((value (read))) (cond ((null value) (return)) (t (print-to-file value)) ) ) )
RETURN The return statement is for exiting from any iteration other than at the natural termination of the looping or passing results back from an iteration
DO (defun mean-of-list (numbers) (do ((sum 0.0 (+sum (first values))) (count 0 (1+ count)) (values numbers (rest values)) ); initial values and updates for locals for do-loop ( (null values) ; termination test (/ sum count) ; result returned ) ; end of end-test/result ) ; end of do-loop (no body) ) ; end of definition
Iteration vs. Recursion • Scanning all the elements in a list: MAPC or DOLIST (if n o results to be returned). MAPCAR (if results to be returned) • Repeating a computation a number of times: DOTIMES, DO • Repeating until some condition is met: DO and LOOP • Testing whether some condition is met. ?
EXERCISE • How would you write the function REMOVE*, given a data-item X and a list L as arguments, that returns a list which is the same as L except that any items equal to X do not appear in this new list using DO rather than recursion?
EXERCISE 2: • You have the following table: Define: (NEWVOTES): function of no arguments, creates and returns a new table with no entries (ADDVOTE): function with three arguments (key, value, table). Returns the table with entered key with value (FINDVOTE): function with two arguments (key, table). Returns the value of key, NIL if no such entry (HASHVOTE): function with two arguments (key, table). Checks if the table contains the key (T or NIL) (EMPTYTABLE): function with one argument (table). Checks if the table has any entries
EXERCISE 3 • (mapcar ‘1+ ‘(1 4 9 16)) • (mapcar ‘evenp ‘(1 2 3 4 5)) • (mapcar ‘type-of (list “my” (+ 1 2) ‘sons)) • (mapcar ‘length ‘(() (()) (()()) (()()()) (()()()()))) • (mapcar ‘+ ‘(1 2 3) ‘(4 5 6)) • (mapcar ‘list ‘(one two three four) ‘(1 2 3 4) ‘(I II III IV)) • (mapcar ‘/ ‘(0 1 2) ‘(3 2 1 0)) • (mapc ‘print (list foo bar baz))
EXERCISE 4 • The following pattern of numbers is called Pascal’s triangle: The numbers at the edge of the triangle are all 1 and each number inside the triangle is the sum of the two numbers above it. Write a procedure that computes elements of Pascal’s triangle by means of a recursive process. 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1
EXERCISE 5 • Define a procedure myreverse that takes a list as argument and returns a list of the same elements in reverse order (myreverse (list 1 4 9 16 25)) (25 16 9 4 1) • Modify the myreverse procedure to produce a deep-reverse procedure that takes a list of arguments and returns as its value the list with its elements reversed and with all sublists deep-reversed as well (deep-reverse ‘((3 4) (1 2))) ((4 3) (2 1))
EXERCISE 6 (define (read-three) (read) (read) (read)) (define (read-xyz) (let ((x (read))) (let ((y (read))) (let ((z (read))) (list x y z))))) • What does (read-three) return when you type “x y z”? • What does (read-xyz) return when you type this input? “x y z”
EXERCISE 7: • Define a function named add-1 that takes as an argument a number and returns the number that is greater than the argument • (map add-1 ‘(1 2 3)) • (map (lambda (x) (*2 x)) ‘(1 2 3)) • Define mylength function to calculate the length of a list
Optional parameters • It can sometimes be useful to define a function so that oen or more arguments can be omitted in some of the uses of the function. For example: > (mklist 9) > (9) > (mklist 9 ‘(1 2 3)) > (9 1 2 3) > (mklist 9 nil) > (9) How this can be done? Optional arguments
Optional parameters (cont.) • (defun mklist (item &optional stuff) (cons item stuff)) (defun f (x &optional (y a)) (print (list x y)) > (setf a 3) > (f 2) > (2 3) (defun f (x &optional (y x)) (list x y)) > (f 3 2) > (3 2) > (f 4) > (4 4)
More about queues • newqueue() • emptyq (queue) • frontitem(queue) • prp(queue) • addtoqueue(item queue) • offqueue(queue)