Functional Programming COMP2003

1 / 25

Functional Programming COMP2003 - PowerPoint PPT Presentation

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

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

PowerPoint Slideshow about ' Functional Programming COMP2003' - herman

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Functional Programming COMP2003

A course on functional programming using Common Lisp

Dr Eleni Mangina

[email protected]

EXERCISES
• Write a Lisp function LLENG which takes two arguments, an integer an a list, and returns T if the length of the list is at least as big as the given integer, NIL if it is shorter than the given length (Hint: there is a LISP function called LENGTH)
• If you wrote LLENG using a COND statement, try writing another version without COND
More exercises
• Write a Lisp function REVFIRST3 which takes one argument, a list, and returns a list containing the first three elements of the list, in the reverse order to their occurrence in the original list. It should give an error (and a suitable message) if the length of the original list is less than 3. You could use LLENG. For example:

> (revfirst3 ‘(a b c d e f))

(c b a)

> (revfirst3 ‘(a b))

Error: REVFIRST3 applied to a list of length less than 3: (a b)

More exercises (cont.)
• Write a Lisp function REVLAST3 which takes one argument, a list, and returns a list containing the last three elements of the list, in the reverse order to their occurrence in the original list. It should give an error (and a suitable message) if the length of the original list is less than 3. (Hint: you do not need recursion). For example:

> (revlast3 ‘(a b c d e f))

(f e d)

Data Structuring and Data Abstraction
• Early Lisp systems had essentially only two kinds of data structure – the list and the property list. These rather low-level structures had then to be used to get the effect of any organization of data that was required. The idea of the association list was not a full data-type, in the sense that only one special purpose accessing function was provided – the rest of the work was done by treating association lists as ordinary lists.
• Common Lisp included proper data-structuring facilities and the defstruct construct is quite sophisticated
Using Lists

If we have some kind of structure or entity that we wish to represent, we could implement its various parts as the elements of a list. For example, suppose we are dealing with a database of people, and each person has four associated attributes – a name, an age, an address and a nationality. We could represent each person item as a four-element list such as:

(“John Major” 49 “10 Downing Street, London” UK)

This would mean we have to define four accessing functions:

(defun person-name (x) (first x))

(defun person-age (x) (second x))

(defun person-nation (x) (fourth x))

Association lists

For simple tables of information, in which data is to be stored against a “key”, an association list maybe used and can be accessed using the built-in function assoc. The list should be set up in the form:

( (<key1> . <value1>)

(<key2> . <value2>)

…..

(<keyN> . <valueN>))

For example, a list of telephone numbers:

( (babbage . 2405)

(minsky . 6067)

(turing . 2333)

)

Association Lists (cont.)

The <key> items can be lists or atoms and the <value> can in fact be one or more items, since assoc returns the whole entry (including the <key>) without regard for how many elements are in it. One could consider the entire rest of this returned item to be the <value>. If there are several entries with the same key, assoc returns only the first. For example, if the variable dictionary holds the list:

( (man noun sing)

(woman noun sing)

(likes verb sing)

(a article)

(the article)

(the article)

(man verb plur)

)

then the following would result:

> (assoc ‘likes dictionary)

(likes verb sing)

>(assoc ‘man dictionary)

(man noun sing)

Association Lists (cont.)

The person example could be implemented using association lists:

( (name “John Major”)

(age 49)

(nationality UK)

)

with appropriate definitions of person-name etc., which would call assoc and second to access the stored values;

DEFSTRUCT

A defstruct expression is like a record definition in many other languages – it declares that the program is to allow certain non-atomic items consisting of various components and that such items will be associated with a particular symbolic name.

A defstruct expression also automatically defines Lisp functions to access the components of such an item, to construct such an item, to recognize such an item and to copy such an item.

DEFSTRUCT (cont.)

( defstruct person

name

age

nationality)

This has the following effects:

• The symbol person becomes the name of a data type
• A function make-person is defined which creates structures of type person
• A function person-p of one argument is defined which gives t when applied to person structures, nil otherwise
• Functions are defined which can access fields of a structure of type person. These functions will be called person-name, person-age, person address and person-nationality
• A function copy-person is defined which, given a structure of type person, will create a new structure containing identical data
DEFSTRUCT (cont.)

Notice that defstruct does not create any structures!

(make-person :name ‘fred :age 33 :address “grosvenor square” :nationality usa)

Structures print out in the form illustrated by:

#\$ (person name ‘fred age 33 address “grosvenor square” nationality usa)

We could also:

> (setf pers1

(make-person :name “pablo” :age 85 :nationality ‘spanish)

#\$ (person name “pablo” age 85 address nil nationality spanish)

DEFSTRUCT (cont.)

> (person-p pers1)

t

> (person-age pers1)

85

Nil

NOTICE THAT WE DIDN’T HAVE TO WRITE DEFUNS FOR THESE FUNCTIONS – THEY ARE CREATED AUTOMATICALLY BY THE defstruct!!

Updating structures

As well as making structures, it is possible to alter the contents of structures, using the setf construct.

) > (setf (person-age pers1) 86))

86

> (person-age pers1)

86

> pers1

#\$(person name “”pablo” age 86 address nil nationality spanish

Updating structures

> (setf pers2 pers1)

> pers2

#\$(person name “”pablo” age 86 address nil nationality spanish

> pers1

#\$(person name “”pablo” age 86 address nil nationality spanish

> pers1

Updating structures (cont.)

> (setf pers3 (copy-person pers1))

> pers3

> pers1

> (setf (person-age pers1) 87)

87

> pers1

> pers3

barcelona

> pers1

> pers3

#\$(person name “”pablo” age 86 address barcelona nationality spanish

When to use what

Use Lists:

when the cluster of items may be of any length and they are all essentially the same sort of thing, in the sense that they are not a group of different kinds of entity held together for convenience – they are more like a set or collections of several items and where you do not want to dip into the set selectively by naming its parts, but are likely to want to scan along it

Use defstruct:

either when what you want to do is take some cluster of different sorts of item (as in the person example) and glue them together into a chunk, individual parts of which you may want to look at (or change) by name; or when you want to have a distinctive data-type that can be recognized as being different from any other sort of entity in the system

SETF

> (setf x ‘(1 2 3))

(1 2 3)

> x

(1 2 3)

> (setf (first x) ‘a)

(a 2 3)

> (setf (cddr x) ‘(d e))

(d e)

> x

(a 2 d e)

SETF

> (setf p ‘(a b c d))

(a b c d)

> (setf r (cons ‘e p))

(e a b c d)

> r

(e a b c d)

> p

(a b c d)

> (setf (first p) 9)

9

> p

(9 b c d)

> r

(e 9 b c d)

RPLACA-RPLACD (for selective alteration of lists)

> (setf p ‘(a b c d))

(a b c d)

> (setf r (cons ‘e p))

(e a b c d)

> r

(e a b c d)

> p

(a b c d)

> (rplaca p 9)

(9 b c d)

> p

(9 b c d)

> r

(e 9 b c d)

TRY RPLACD!!

NCONC

> (setf p ‘(a b c d))

(a b c d)

> (setf r ‘(e f g h))

(e f g h)

> (nconc p r)

(a b c d e f g h)

> r

(e f g h)

> p

(a b c d e f g h)

QUEUES

> (setf q1 (newqueue))

> (empty q1)

t

> (prp q1)

<<3>>

> (prp q1)

<<3 4>>

> (offqueue q1)

3

> (prp q1)

<<4>>

> (offqueue q1)

4

> (prp q1)

<<>>>

> (empty q1)

t

Watch any unpleasant side-effects

(defun shownumber (y)

(let ((x ‘(1)))

(print x)

(setf (first x) y)

)

)

> (shownumber 9)

(1)

9

>(shownumber 40)

(9)

40

ARRAYS

> (make-array ‘(10 12))

> (make-array ‘(3))

There is a simple way to define that all elements of an array are to be set to a particular value:

(defvar *table* (make-array ‘(12 12) :initial-element 0)

(make-array ‘(10) :initial-element (cons ‘a nil))

Accessing arrays:

(aref *table* 6 9)

Updating arrays:

(setf (aref *table* 4 8) ‘hello)

VECTORS

#(a b c)

(setf *alphabet* #(a b c d e f g h I j k l m n o p q r s t u v w x y z))

>(aref *alphabet* 4)

e