atom(ITEM)-> BOOLThis will be true for all items except pairs, and false for pairs. This is therefore equivalent to not(ispair(ITEM)).
islist(ITEM) -> BOOLThis is intended to recognize the empty list [], dynamic lists, or ordinary lists. However, for efficiency it does not check that all the links in the chain have lists in their tail, and so it can be fooled. e.g.
islist(conspair(3,4)) =>
** <false>
islist(conspair(2,conspair(3,4))) =>
** <true>
The latter is not really a list because it does not end in []. A "proper"
list recognizer would be something like this
define is_really_list(item);
if islist(item) then
if null(item) then true
elseif atom(item) then false
else is_really_list(tl(item))
endif
else
false
endif
enddefine;
is_really_list(conspair(2,conspair(3,4))) =>
** <false>
is_really_list(conspair(1, conspair(2,conspair(3,4)))) =>
** <false>
is_really_list(conspair(1, conspair(2,conspair(3,[])))) =>
** <true>
The above definition could be optimised slightly by checking for dynamic
lists directly on the basis of the definition of dynamic lists instead
of using islist to do that.
ispair(ITEM) -> BOOLA recognizer for pair datastructures.
islink(ITEM) -> BOOL
This is equivalent to
ispair(TIEM) and not(null(item))
null(ITEM) -> BOOL
This recognizes empty lists, including empty (exhausted) dynamic lists.
If ITEM is a dynamic list that has not been expanded it will expand it
by one step, so that front and back can be used on that link instead of
hd and tl, in order to avoid repeating the test for a dynamic list.
isdynamic(ITEM) -> PRecognizes dynamic lists. If ITEM is a dynamic list it returns the generator procedure, otherwise it returns false.
member(ITEM, LIST) -> BOOLThis procedure returns true if ITEM is an element of the list LIST, otherwise false, equality being determined with the operator "=".
lmember(ITEM, LIST) -> SUB_LIST
This is like member except that
1. The test for equality is "==" not "="
2. If ITEM is found to be == to an element of the list, then the
procedure returns the trailing portion of LIST starting with
that element
lmember("on", [the cat sat on the black mat]) =>
** [on the black mat]
In a language like Pop-11 it is very easy to define additional list processing procedures. For example, a slight variant of maplist would take a list and two procedures and return a list of two element lists:
define map2list(list, proc1, proc2) -> list;
[%
lvars item;
for item in list do [%proc1(item), proc2(item)%] endfor
%] -> list
enddefine;
map2list([1 -2 3 -4 5 -6], identfn, negate) =>
** [[1 -1] [-2 2] [3 -3] [-4 4] [5 -5] [-6 6]]
A procedure to merge two lists by interleaving elements:
define merge(list1, list2) -> list;
lvars item1, item2;
[%
for item1, item2, in list1, list2 do item1, item2, endfor
%] -> list
enddefine;
merge([1 2 3 4], [a b c d]) =>
** [1 a 2 b 3 c 4 d]
Note if either list has more elements than the other this procedure will
ignore trailing items in the longer list.
The variety of possible user defined list manipulating procedures is endless. In Poplog Pop-11 several examples can be found in the library directories, i.e. $usepop/pop/lib/auto and $usepop/pop/lib/lib