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) -> BOOLThis 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