?he 'LISTS1''Page %'
?fo 'Aaron Sloman'- % -'April 1977'
.ce 2
LIST PROCESSING CRIB SHEET
==========================

Before trying this sheet you are advised to work through INTRO2.

Here is a collection of little examples which should extend your
understanding of list processing.
Try to think about them before you try them out at the teletype.
See if you can guess what the effects will be if you type the examples in.
NB - some of them contain errors!

 	: VARS LIST; [1 2 3 4 5] -> LIST;
 	: LIST =>

We declared a variable called LIST, and assigned a list of numbers to it,
then used the print arrow to print out the value of LIST.

The functions HD and TL can be used to find out what is in a list.
To get the first element use HD:

 	: HD(LIST) =>

To get the rest of the list use TL:
 	: TL(LIST) =>

Notice what happens if you don't leave spaces between the numbers
when you type in a list:

 	: HD([1234]) =>
 	: TL([1234]) =>

 	: LENGTH([1234])=>
 	: LENGTH ([1 2 3 4]) =>

 	: HD([C A T]) =>
 	: HD([CAT]) =>
 	: TL([C A T]) =>
 	: TL([CAT]) =>
 	: LENGTH ([C A T]) =>
 	: LENGTH ([CAT]) =>

The concatenation operator can be used to make a bigger list containing
all the elements of "<>", and additional elements, thus:

 	: [ 0 ] <> LIST =>
 	: [1] <> LIST =>
 	: [CAT] <> LIST =>
 	: [CAT DOG] <> LIST =>
 	: [CAT DOG] <> [PIG COW] =>
 	: LIST <> [CAT DOG] =>
 	: LIST <> LIST =>
 	: 0 <> LIST =>
 	: LIST <> 0 =>

Notice that both arguments for <> must be lists.

Instead of simply printing out the new list, you can assign it to a
variable, then do things with it:

 	: VARS LIST2;
 	: [0] <> LIST -> LIST2;
 	: LIST2 =>
 	: [NUMBERS] <> LIST2 =>
 	: LIST2 <> LIST1 =>

If you want to put a number represented by an arithmetic expression
into a list you'll need to use "decorated" list-brackets: [%   %] e.g.
e.g.:

 	: [% 6*9 %] <> LIST2 =>

If you put several things into decorated list-brackets, they
need to be separated by commas, like the arguments of a function,
e.g.

 	: [% -2, 6*9 %] <> LIST2 =>
 	: [% -3, -2, -1 %] <> LIST2 -> LIST2;
 	: LIST2 =>

Decorated list brackets are required when you wish to build
a list containing the value of some variable.

 	: VARS X;
 	: 0 -> X;

We have defined
a variable called X, and given it the value 0.  We can create a new
list containing the value of X and all the elements of LIST as follows:


 	:  [% X %] <> LIST =>

contrast the following:

 	: [X] <> LIST =>

Use decorated list brackets when you want to get the value of a variable
put in a list, rather than the word naming the variable.

To get the word itself in the list, either use undecorated list brackets,
or else use the word-quote symbol on either side of the word, e.g.:


 	: [% "X" %] =>
 	: [% X %] =>
 	: VARS Y;
 	: -2 -> Y;
 	: Y =>
 	: [% Y %] =>
 	: [%Y, X %]  =>
 	: [Y X] =>
 	: [% Y, X %] <> LIST =>

In fact, you can include lots of POP11 instructions within decorated
list brackets and all their results will be included in the list
e.g.:

 	: [% X, Y, 1 + 1, Y * Y, "CAT" %] =>
 	: LENGTH(LIST) =>
 	: LENGTH( LIST <> LIST ) =>
 	: [% LENGTH(LIST), LENGTH( LIST <> LIST ) %] =>

You can include one list inside another:

 	: [% LIST, LIST2 %] =>
 	: [% HD(LIST), HD(LIST2), TL(LIST), TL(LIST2) %] =>

That was a list of four elements, of which the last two were lists.


Try to define a function to check if an item is an element of a list
The function is to take two arguments, an item and a list.
Its task is to decide whether the item is an element of the list,
and if so, to produce the result true, otherwise the result false.
If the list is empty, i.e. if it is [], then the result should be false.

Here is one method:

 	: FUNCTION MEMBER(ITEM,LIST);
 	:	IF	LIST = []
 	:	THEN	FALSE
 	:	ELSEIF	ITEM = HD(LIST)
 	:	THEN	TRUE
 	:	ELSE	MEMBER(ITEM,TL(LIST))
 	:	CLOSE
 	: END;

This says if the list is [] then the result is false.  Otherwise see
if the item is the first element of the list, and if so the result is
true.  
Otherwise start again trying to see if the item is a member of the TL
of the list (i.e. the rest of the list).  Now try it.

 	: MEMBER(3, [1 2 3 4 5]) =>
 	: MEMBER(3, [1 2 4 5]) =>

By tracing the function you can get a clearer understanding of how it
works:
 	: TRACE MEMBER;

 	: MEMBER(3, [1 2 3 4 5]) =>
 	: MEMBER(33, [1 2 3 4 5]) =>
 	: MEMBER("CAT", [1 2 3 4 5]) =>
 	: MEMBER("CAT", [DOG MOUSE CAT 3 4 5]) =>

 	: MEMBER("CAT", []) =>
 	: MEMBER(99, []) =>
 	: MEMBER([], []) =>
 	: MEMBER([], [ A B C [] E [F G]] ) =>
 	: MEMBER( "A", [ [A] [B]  A B ]) =>

 	: MEMBER("A", [% "A" %] <> [B C D] ) =>
 	: MEMBER("A", "A" <> [B C D]) =>
 	: [A B C] -> LIST;
 	: MEMBER(LIST, [% LIST %] <> [B C D]) =>
 	: MEMBER(LIST, LIST <> [B C D]) =>
 	: MEMBER(HD(LIST), LIST <> [B C D]) =>

Can you explain all those results?

Try defining a function called JOIN2, which takes two arguments and 
makes a list out of them.

 	: FUNCTION JOIN2(ITEM1,ITEM2);
 	:	[% ITEM1, ITEM2 %]
 	: END;

 	: JOIN2(3,4) =>
 	: JOIN2("CAT", 99) =>
 	: JOIN2("CAT", "CAT") =>
 	: JOIN2(99,99) =>
 	: JOIN2("CAT", [A B C]) =>
 	: JOIN2([A B C], "CAT") =>

Now define a function which takes three items and makes a list 
out of them.

What about a function which produces the N'th element
of a list, where N is a number?
 	: FUNCTION ELEMENT(N,LIST);
 	:	IF	N = 1
 	:	THEN	HD(LIST)
 	:	ELSE	ELEMENT(N-1,TL(LIST))
 	:	CLOSE
 	: END;

This says define a function called ELEMENT which takes two arguments
a number and a list.  If the number is 1, then the result of the function,
is the HD, i.e. the first element, of the list.
Otherwise subtract 1 from the number, and start again with
the TL of the list.
.br
Now try the function on some examples:

 	: ELEMENT(1, [A B C]) =>
 	: ELEMENT(3, [A B C D]) =>

 	: TRACE ELEMENT;
 	: ELEMENT(1, [A B C D]) =>
 	: ELEMENT(3, [A B C D]) =>
 	: ELEMENT(1, []) =>
 	: ELEMENT(6, [A B C D]) =>

Can you put a test inside the definition of function ELEMENT, so that
if the list is too short it gives the result "UNDEF".  You need to test
if the list gets down to [].

 	: ELEMENT(0, [A B C D]) =>
 	: ELEMENT(-3, [A B C D]) =>

 	: VARS X Y Z;
 	: 1 ->X; 2 ->Y; 3 ->Z;
 	: [% X, Y, Z %] =>
 	: [ X, Y, Z ] =>
 	: LENGTH ([X, Y, Z]) =>
 	: LENGTH ( [% X, Y, Z %]) =>
 	: REV([ X, Y, Z]) =>
 	: REV([% X, Y, Z%]) =>
 	: REV([% "X", "Y", "Z" %]) =>
 	: [%"X", X , "Y", Y %] =>
 	: REV([C A T]) =>
 	: REV([CAT]) =>
 	: REV([CAT DOG]) =>
 	: REV([CATDOG]) =>
Note the difference between a list containing two words "CAT" and "DOG"
and a list containing the single word "CATDOG". The space in
 	[CAT DOG]
.br
tells POP11 that you want the list to contain two separate words.

Instead of using the percept symbol "%" to get the value of a word into
a list, i.e. to "unquote" the word, you can use the up-arrow symbol
"^" (represented by an arrow pointing up on teletype keyboards).
Thus:
 	: VARS X Y;
 	: 3 -> X;
 	: 4 -> Y;
 	: [X Y] =>
 	: [^X Y] =>
.br
The prefix "^" before "X" says, "use the value of".
 	: [X ^Y] =>
 	: [^X ^Y] =>
 	: [THERE ARE ^X CATS AND ^Y DOGS] =>
 	: 5 ->X; 99 ->Y;
 	: [THERE ARE ^X CATS AND ^Y DOGS] =>

We can give a repeat command, making POP11 print out the same list
several times, except that different values of X and Y are used
each time. This illustrates a use for the uparrow prefix:
.br
.ne 5
 	: REPEAT 5 TIMES
 	:	X + 1 -> X;
 	:	Y + 1 -> Y;
 	:	[THERE ARE ^X CATS AND ^Y DOGS] =>
 	: CLOSE;
Notice that
 		[THERE ARE ^X CATS AND ^Y DOGS]
.br
is really equivalent to the following, only slightly neater:
 		[THERE ARE %X% CATS AND %Y% DOGS]
.br
and also equivalent to:
 	[% "THERE", "ARE", X, "CATS", "AND", Y, "DOGS" %]
.br
The commas are needed if you put several items between a pair of
percent symbols, otherwise you get a "missing separator" mishap message.


Here's a function to create lots of numbers. Try it out.
 	: FUNCTION MAKENUMBERS(NUM);
 	:	IF	NUM < 1
 	:	THEN	0
 	:	ELSE	NUM;
 	:		MAKENUMBERS(NUM - 1)
 	:	CLOSE
 	: END;

 	: MAKENUMBERS(4) =>
 	: TRACE MAKENUMBERS;
 	: MAKENUMBERS(3) =>
 	: MAKENUMBERS(-5) =>
 	: MAKENUMBERS(3) =>

We can use the function MAKENUMBERS to make a lot of numbers to be put into
a list, thus:
 	: UNTRACE MAKENUMBERS;
 	: [% MAKENUMBERS(4) %] =>
 	: [% MAKENUMBERS(10) %] ->LIST;
 	: LIST=>
 	: ELEMENT(4, [% MAKENUMBERS(10) %]) =>
 	: [%MAKENUMBERS(5) %] <> [%MAKENUMBERS(4)%] =>
 	: [%MAKENUMBERS(4)%] <> REV([% MAKENUMBERS(4) %] =>

Define a function called LISTNUMS which takes a number and makes a
list of all the numbers from 0 up to that number, e.g.
listnums(5) should produce the list[0 1 2 3 4 5]
You could use the following format:

 	: FUNCTION LISTNUMBERS(NUM);
 	:	IF	NUM < ...
 	:	THEN	...
 	:	ELSE	LISTNUMBERS(...) <> ...
 	:	CLOSE
 	: END;
.br

What should go in place of the dots?
Test your function with

 	: LISTNUMBERS(3) =>
 	: LISTNUMBERS(0) =>

Define a function called
PALINNUM
such that:
 	: PALINNUM(5) =>
 	** [5 4 3 2 1 0 1 2 3 4 5]
.br
Here is a 'schema' for
PALINNUM:
 	: FUNCTION PALINNUM(NUM);
 	:	IF	NUM = 0
 	:	THEN	[0]
 	:	ELSE	[% ... %] <> PALINNUM(...) <> [% ... %]
 	:	CLOSE
 	: END;
.br

 	: PALINNUM(4) =>
 	: PALINNUM (-3) =>

NB - to stop the computer printing out long error
messages type
CTRL-X.
What went wrong in the second example?
If you don't understand ask your tutor.
Try revising
PALINNUM
so that:
 	: PALINNUM(-3) =>
 	** [-3 -2 -1 0 -1 -2 -3]
.br
A suitable schema might be:
 	: FUNCTION PALINNUM(NUM);
 	:	IF	NUM = 0
 	:	THEN	...
 	:	ELSEIF	NUM < 0
 	:	THEN	...
 	:	ELSE	...
 	:	CLOSE
 	: END;
.br
If you solve this problem try simplifying your solution
given that the following is 'legal'
POP11:
 	: PALINNUM(IF NUM < 0 THEN ... ELSE ... CLOSE)
.br

Write out descriptions, in English, with diagrams if you think they
help, explaining what the following do:

 	:  [    ]
 	: [%    %]
 	: <>
 	: REV
 	: LENGTH

 	: HD 
 	: TL


and any functions you have defined, e.g.

 	: MEMBER
 	: ELEMENT
 	: MAKENUMBERS
 	: LISTNUMBERS
 	: PALINNUM
