next up previous contents
Next: Iterating on lists Up: CHAPTER.6: LIST PROCESSING Previous: Some procedures for

Predicates on lists

atom, islist, ispair, islink, null

atom(ITEM)-> BOOL
This will be true for all items except pairs, and false for pairs. This is therefore equivalent to not(ispair(ITEM)).

islist(ITEM) -> BOOL
This 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) -> BOOL
A 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

isdynamic(ITEM) -> P
Recognizes dynamic lists. If ITEM is a dynamic list it returns the generator procedure, otherwise it returns false.

member, lmember

member(ITEM, LIST) -> BOOL
This 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]

user defined predicates

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



next up previous contents
Next: Iterating on lists Up: CHAPTER.6: LIST PROCESSING Previous: Some procedures for



Aaron Sloman
Fri Jan 2 03:17:44 GMT 1998