next up previous contents
Next: The matcher arrow Up: CHAPTER.7: THE POP-11 Previous: Use of the

The use of "?" variables

The variable preceded by "??" in the above example matched a segment of the list. We can also use a variable to match a single element of a list, and have that element assigned as its value. For example, here is a way of getting the third element of a list assigned to the variable "item". We use "=" as an anonymous pattern element to match exactly one element of the datum without saving the value and "?item" to match one element and save the value in the variable item.

    vars item;
    [ the cat sat on the mat] matches [ = = ?item ==] =>
    ** <true>

    item =>
    ** sat
Here we use the matcher to extract the third and fourth elements of a list:

    vars third, fourth;
    [the cat sat on the black mat] matches [= = ?third ?fourth ==] =>
    ** <true>

    third =>
    ** sat
    fourth =>
    ** on

Example: Using the matcher to define next_item

Consider how to define a procedure that searches down a list looking for a given item, and if it finds it returns the next item. You could write that using normal list processing procedures as follows:

    define next_item(item, list) -> next;
        repeat
            if list = [] then
                false -> next;
                return();
            elseif hd(list) = item then
                ;;; found the target, get the next item and stop
                hd(tl(list)) -> next;
                return()
            else
                ;;; move one step down the list.
                tl(list) -> list;
            endif
        endrepeat
    enddefine;
Here is a version using the pattern matcher.

    define next_item(item, list) -> next;
        vars found;  ;;; this is to be used as a pattern element

        if list matches [ == ^item ?found ==] then
            found -> next
        else
            false -> next
        endif
    enddefine;
Note that we use "^item" as explained previously to insert the value of the variable item in the pattern. This means that instead of our programs always having fixed patterns they can have dynamically constructed patterns.

Now test the procedure

    vars person = [name sue age 30 job teacher home york];
    next_item("age", person) =>
    ** 30
    next_item("home", person) =>
    ** york
    next_item("height", person) =>
    ** <false>
That example should illustrate how much easier it is to use the matcher than ordinary list processing in such cases. Programs using the standard list processing method will run faster, however. If that is important, program using the matcher can be "translated" after they have been developed.

Exercise: define previous_item

Using the above example as a template produce a definition of a procedure called previous_item that behaves thus:

    vars person = [name sue age 30 job teacher home york];
    previous_item(30, person) =>
    ** age
    previous_item("york", person) =>
    ** home
    previous_item("height", person) =>
    ** <false>


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