TEACH LISTSUMMARY Aaron Sloman, updated Oct 1986 A PARTIAL SUMMARY OF LIST-PROCESSING IN POP11 CONTENTS - (Use g to access desired sections sections) -- CREATING LISTS -- ACCESSING COMPONENTS OF LISTS -- MISCELLANEOUS PROCEDURES -- GLOBAL VARIABLE (EMPTY LISTS) -- CREATING LISTS ----------------------------------------------------- >>>> [ ] These "list constant brackets" may contain text items, i.e words, numbers and strings. E.g.: [ a b c d] is a list of four words [1 cat 2 dog 3 pig ] is a list of six items. [string 'a short string' 66] is a list with a word a string and a number. [] is the empty list. Can also be called NIL. List brackets may also contain lists, E.g.: [ [1 2] [3] 4 ] is a list with two lists and one number. It contains exactly three elements, of which the first contains two. >>>> [% %] These "decorated list brackets" are used to create lists whose contents depend on the values of variables or the results of executing procedures. For instance: [% 3, cat, hd(l) %] is a list containing the number 3, the value of the variable CAT and the first element of L, which must be a list, whereas [ 3, cat, hd(l) ] contains the number 3, the comma, the word "CAT", a comma, the word "HD", the word "(", etc. [% [% a %], [% b, c%], [% d %] %] is a list of three lists, whose contents depend on the values of A B C and D. >>>> ^ (the "up-arrow" or "hat" symbol) Can be used in place of "%". For example [ ^x + ^y is ^(x + y) ] is the same as [% x, "+", y, "is", x + y %] and [ %x% + %y% is %x + y% ] When followed by a variable, "^" means: "use the value of this variable". When followed by a parenthesised expression, it means: "use the value of the parenthesised expression". >>>> ^^ (double "up-arrow" or "hat" symbol) This is used to merge the contents of a list into an enclosing list. Thus: [ b c d ] -> list; [a ^list e ] => ** [a [b c d] e] [a ^^list e ] => ** [a b c d e] The prefix "^^" can be thought of as "remove the list brackets". >>>> :: This is an operation for joining an element onto an existing list, to make a new list, e.g. 3 :: [4 5 6] is a list of four numbers. "cat" :: [] is the same as [cat] "cat" :: "dog" will cause an error, since :: must have a list as its second argument. Notice that x :: y is equivalent to [^x ^^y] The operation :: is easier for the machine, but otherwise has no advantage. >>>> CONSPAIR This is a procedure, which can be thought of as equivalent to :: . That is conspair(x,l) is the same as x :: l The only difference is that the second argument of CONSPAIR need not be a list. E.g. conspair(3, 4) -> l; l => ** [3|4] ;;; note the use of the vertical bar - indicating that ;;; the second element is not a list tl(l) => This now produces an error, because TL insists on a proper list, and a pair whose second element is not a pair is not acceptable. The procedure BACK has no such qualms. back(l) => ** 4 CONSPAIR is rarely needed in straightforward programs. >>>> <> This is an operator which takes two lists and "concatenates" them to produce a new list. The first list is copied, so that the original does not have any extra elements added to its end. E.g. [cat dog ] <> [pig mouse] is the same as: [cat dog pig mouse] lista <> listb means: make a new list containing the elements of LISTA and the elements of LISTB. [^x] <> l -> l is the same in effect as x :: l -> l; or [^x ^^l] -> l; But the former is much less efficient, since <> copies the first list. Notice that when X and Y are lists: x <> y is equivalent to [^^x ^^y] The former has no advantages except that it is easier for the machine. The operator <> can also be used to join two words, two vectors, two strings. >>>> REV This is a procedure which takes a list as argument and creates a new one containing the same elements in reverse order. E.g. rev([a b c]) is [c b a] >>>> MAPLIST This is a procedure which takes a list and a procedure and applies the procedure to every element of the list, finally creating a new list containing all the results. E.g. maplist(l, identfn) makes a copy of the list l. maplist([cat dog 2 mouse 3 4 ], isword) => ** [ ] It could have been defined thus, were it not in the system: define maplist (l,f); vars x; [% for x in l do f(x) endfor%] enddefine; Compare the procedure APPLIST. >>>> DATALIST This procedure can be applied to a word, string, or vector. It will create a list containing all the elements of the word string or vector. The elements of a word or string will be the numbers representing the characters in it. (The code for lower case A is 97, for B 98, for Z 122.) So: datalist('abz') and datalist("abz") both give the list [97 98 122] maplist([cat dog mouse], datalist) => ** [ [99 97 116] [100 111 103] [109 111 117 115 101] ] This produces a list of lists of character codes. (See MAPLIST, above.) NOTE: strictly, the above codes refer to the LOWER CASE characters. -- ACCESSING COMPONENTS OF LISTS -------------------------------------- >>>> HD This procedure takes a list as argument and returns the first element of the list. HD(LIST) is equivalent to LIST(1). (See below). >>>> TL This procedure takes a list as argument and returns as its result the sublist containing all but the first element. E.g. if L is a list then: hd(tl(l)) is the second element hd(tl(tl(l))) is the third element = l(3) >>>> LAST This library procedure, when applied to a list returns its last element: last([a b c d]) => ** d Notice that: last(x) is equivalent to: x(length(x)) >>>> Numerical subscripting of lists In POP11 lists can be treated as procedures which take a number N, to get the N'th element of a list. E.g. vars l; [a b c d] -> l; l(2) => ** b l(3) => ** c The N'th element can also be altered by an assignment. Thus to replace the third element with the list [THIRD ELEMENT], do: [third element] -> l(3); l => ** [a b [third element] d] l(3) => ** [third element] -- MISCELLANEOUS PROCEDURES ------------------------------------------- >>>> LENGTH This procedure takes a list and counts the elements, returning a number as its result. E.g length([ 99 a [a b c] d]) is 4 length([]) is 0 >>>> ATOM This is a type-testing procedure, which returns TRUE or FALSE as its result. IF it is applied to a non-empty list (i.e. a list other than []), its result is FALSE. If it is applied to anything else, e.g. a word, a procedure, a string, or [], the result is TRUE. So: atom([]) is true atom(99) is true atom("cat") is true atom(hd) is true atom([cat dog]) is false atom(3 :: []) is false >>>> APPLIST This procedure takes a list and a procedure and applies the procedure to every element of the list. (Compare MAPLIST.) E.g. applist([ 99 ], isinteger) yields , applist([ 1 2 a b 3], isinteger) puts on the stack: ,,,, whereas applist([], f) does nothing, whatever procedure F is. APPLIST could have been defined like MAPLIST (above), but without the decorated list brackets. >>>> ISPAIR This is TRUE if applied to a list (other than the empty list) FALSE otherwise. -- GLOBAL VARIABLE (EMPTY LISTS) -------------------------------------- >>>> NIL This is a variable provided by the system whose value is the word "[]" so that [], NIL, and VALOF("NIL") all refer to the same thing. [] is conventionally used to represent the "empty" list, so that if you take a list L and then assign TL(L) to L repeatedly, you'll end up with L having the value []. Trying to apply HD or TL to [] will produce an error ("non-list argument for list procedure, culprit []"). For more on lists see R.Barrett, A.Ramsay, A.Sloman, POP-11: A Practical language for Artificial Intelligence Ellis Horwood and John Wiley, 1985. Also, try the following TEACH files. TEACH * LISTS *ARROW *PERCENT * MATCHES * MOREMATCH * DATABASE TEACH * SETS ------------