130 likes | 237 Views
Data Structur es (defstruct) and Data Abstraction. Using Lists.
E N D
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: (“Tony Blair” 45 “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-address (x) (third x)) (defun person-nation (x) (fourth x))
Association lists: the assoc function For simple tables of information, in which data is to be stored against a “key”, an association list maybe used and can be accessed usingthe 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) )
Using the assoc function 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 singular) (woman noun singular) (likes verb singular) (a article) (the article) (the article) (man verb plural)) then the following would result: > (assoc ‘likes dictionary) (likes verb singular) >(assoc ‘man dictionary) (man noun singular)
Association Lists again The person example could be implemented using association lists: ( (name “Tony Blair”) (age 45) (address “10 Downing Street”) (nationality UK) ) with appropriate definitions of person-name etc., which would call assoc and second to access the stored values; (defun person-name (p) (second (assoc ‘name p))) (defun person-address (p) (second (assoc ‘address p))) and so on
DEFSTRUCT: a lisp keyword 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 address 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
Note the colons (:) before the defstruct components! These must always be present before component names. DEFSTRUCT (cont.) Notice that defstruct does not create any structures: it just defines the type! >(make-person :name ‘fintan :age 33 :address “ranelagh” :nationality irish) Structures print out in the form illustrated by: #$ (person name ‘fintan age 33 address “ranelagh” nationality irish) 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-name pers1) pablo > (person-age pers1) 85 Notice that we didn’t have to write definitions for the functions person-p person-name etc. These functions are created automatically for us by 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)
Here, changes to pers1 also cause changes to pers2. (the pers1 and pers2 variables both point to the same thing) 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) > (setf (person-address pers1) ‘madrid) madrid > pers2 #$(person name “pablo” age 86 address madrid nationality spanish)
This function creates a copy of the person struct passed in If we change a value in one person, the copy doesn’t change Copying structures > (setf pers3 (copy-person pers1)) > pers3 #$(person name “pablo” age 86 address madrid nationality spanish) > pers1 #$(person name “pablo” age 86 address madrid nationality spanish) > (setf (person-age pers1) 87) 87 > pers1 #$(person name “pablo” age 87 address madrid nationality spanish) > pers3 #$(person name “pablo” age 86 address madrid nationality spanish)
When to use defstruct 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