functional programming comp2003 a course on functional programming using common lisp dr eleni...

31
Functional Programming COMP2003 A course on functional programming using Common Lisp Dr Eleni Mangina [email protected]

Post on 19-Dec-2015

236 views

Category:

Documents


3 download

TRANSCRIPT

Functional Programming COMP2003

A course on functional programming using Common Lisp

Dr Eleni Mangina

[email protected]

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)))) ))

EVERYThis 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

SOMEThis 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)))

)246t

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

DOTIMESIt 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))

))

))

LOOPThe 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))

)

)

)

RETURNThe 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

Washington 11

Oregon 7

Iowa 7

California 54

Florida 25

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.

11 1

1 121 13 3

1 14 46

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)))))

a. What does (read-three) return when you type “x y z”?

b. 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)