In our example so far, we have used all the information in the list rooms in a rather verbose fashion. If we wanted to find information about a particular room, e.g. room3, we could use our knowledge of the order of the items in the list rooms, and get the third element and give it to display_room, using the expression `rooms(3)' to denote the third element of the list called `rooms', thus:
display_room(rooms(3)); INFORMATION CONCERNING: room3 perimeter is: 52 area is: 165 volume is: 1320But if we do not know the order in which information is stored, then we can define a procedure to search in the list for information about the room required. We want a procedure called findroom which
a. takes two inputs: a room name and a list of data about all rooms b. produces the list of data for the named room as its resultFor example
findroom("room3", rooms)should produce as its result, to be left on the Pop-11 stack, the list
[room3 15 11 8]We can do this, using techniques already illustrated, by using a "for" loop, and examining each piece of room information in turn until we find one whose first element is the name of the required room. At that point we can stop the search, using the "return()" command. If we get to the end of the list without finding the relevant room, produce a "mishap" message.
define findroom(name, list_of_lists) -> data; ;;; search list_of_lists for a list starting with name for data in list_of_lists do if data(1) = name then return(); ;;; i.e. stop the procedure endif; endfor; ;;; produce a mishap message mishap('DATA NOT FOUND', [^name ^list_of_lists]) enddefine;We have again used the format:
for <item> in <list> do <action> endforThis time instead of the <action> containing a single simple instruction that is to be obeyed with every room it contains a complex construction, with a part that is to be applied only if a condition is to be satisfied. The <action> is a conditional imperative, of the form:
if <condition> then <action> endifLater we'll meet alternative forms of conditionals. The action in this case is simply to `return', i.e. to jump to the end of the procedure. Because `data' is specified as an output local variable in the procedure header, the value of `data' which made the condition
data(1) = nametrue will be the result of the procedure. In other words the result will be the list of information about the room with the name specified.
We can test findroom as follows using the word-quote symbol `"' to say that the first input given to findroom is a word, not its value. We use the print arrow `=>' to print out the result produced by findroom and left on the stack.
findroom("room3", rooms) => ** [room3 15 11 8] findroom("room5", rooms) => ** [room5 21 11 9]Alternatively the output of findroom can be given as input to display_room, e.g.
display_room( findroom("room5", rooms) );(Try that.)
And if we give it a room which can't be found we get a mishap message:
findroom("room17", rooms) => ;;; MISHAP - DATA NOT FOUND ;;; INVOLVING: room17 [[room1 14 12 8] [room2 16 11 8] [room3 15 11 8] [room4 10 9 9] [room5 21 11 9]] ;;; FILE : /home/staff/aaron/primer LINE NUMBER: 2310 ;;; DOING : findroom ....... ......The message will contain more information, and will have a different file name and line number for you. The extra information can be ignored for now, though it may be relevant when debugging complex programs. This `mishap' message is produced by the line in our procedure definition which invokes the built in procedure called "mishap" (which is actually re-definable by the user, if different error handling is required.)
At this stage it may be difficult to understand everything in the definition of the procedure findroom. After reading later chapters on list processing, conditionals, and looping constructs, it may be useful to look back at this chapter, which may then make more sense.
Findroom is sufficiently general to be given different lists of rooms on different occasions. We can use it to define a more complex procedure called `find_and_show' to print out the data concerning a given room. This procedure is to be given the name of a room (a word) and the list of information about all rooms. It uses findroom to dig out the list of data about the particular room, and gives that to display_room for printing. Here is a possible definition of find_and_show:
define find_and_show(name, list_of_lists); display_room( findroom(name, list_of_lists) ); enddefine;Notice that the two items given as input to find_and_show are simply handed on as input to findroom. The latter produces a result which is used as input for display_room. The same thing could be said less compactly, though perhaps more clearly, by using an extra local variable "room" in the procedure below, to hold the result produced by findroom.
define find_and_show(name, list_of_lists); lvars room; findroom(name, list_of_lists) -> room; display_room(room); enddefine;To test the procedure, we can type:
find_and_show("room2", rooms);Which produces the following printout:
INFORMATION CONCERNING: room2 perimeter is: 54 area is: 176 volume is: 1408Note that find_and_show does not produce a result (it has no output local variable, and leaves nothing on the Pop-11 stack). Instead it does some printing via display_room.
Because find_and_show produces no result our test imperative instruction does not use the print arrow "=>" to print out a result. Instead the instruction is terminated with a semi-colon.