next up previous contents
Next: Exercise using properties Up: CHAPTER.4: PROCEDURES IN Previous: Arrays are procedures

Properties as procedures

An N dimensional array provides a mapping or association from sets of N integers to values stored in the array.

Pop-11 also allows the creation of entities called "properties" that will map or associate any objects with any others. There are various ways of creating properties in Pop-11, depending on the particular sort of mapping that is required.

newmapping associates things compared using "="

A major decision in setting up an association or property is to decide what to do about two objects that are structurally similar with identical components, but are not the very same object. Should they be mapped onto the same thing or not? If so, use newmapping, otherwise use newproperty. (Actually newmapping is based on a more general procedure, newanyproperty, which will not be described here.)

Newmapping takes four arguments

    a. A list giving an initial mapping. (This list will be empty
       in our examples here.)

    b. An integer indicating the size the mapping is likely to grow to.
       This is actually used to decide the amount of space initially
       allocated to store the associations.

    c. A default item, with which everything is assumed to be
       associated. (Often the Pop-11 object false, or undef is used.)

    d. A boolean, i.e. the value true or false, which controls
       whether the space allocated for the mapping should be increased
       when appropriate, in order to increase the speed with which
       values are found.
(The second and fourth items merely affect efficiency, in most cases, and make no difference to the logic of the program.)

For example, suppose you were storing information about individuals, where an individual was always represented by a list like [john smith], [marylou walker], etc.

Then if you store information about each individuals by associating it with the lists, then if you re-created a list [john smith] later on, you might want the new list to be associated with the same information as the old list. In that case you should use newmapping, not newproperty.

For example, here are several mappings created using newmapping, with table sizes 10, default values 0 or false, and expandability set to true:

    vars
        age = newmapping([], 10, 0, true),
        spouse = newmapping([], 10, false, true),
        occupant = newmapping([], 10, false, true);
We can then store information about different people, and rooms:

    33 -> age([john smith]);
    27 -> age([marylou walker]);

    [john smith] -> spouse([judy smith]);
    [mary low walker] -> spouse([bob walker]);

    [john smith] -> occupant([room 3]);
    [bob walker] -> occupant([room 5]);
    [ted bloggs] -> occupant([room 6]);
We can then ask for information:

    age([marylou walker]) =>
    ** 27

    age(spouse([judy smith])) =>
    ** 33

    occupant([room 4]) =>
    ** <false>

    occupant([room 3]) =>
    ** [john smith]

Properties created using newmapping behave like procedures

Notice that the syntax for finding out what each property associates with an object is the same as the syntax for applying a procedure to an object. The properties, age, occupant and spouse are all both properties and procedures. We can test for this using the built in predicates isproperty and isprocedure:

    isproperty(age) =>
    ** <true>

    isprocedure(age) =>
    ** <true>
Compare:

    isproperty(hd) =>
    ** <false>

    isprocedure(hd) =>
    ** <true>
Using newmapping we created properties that would give the same result for lists created at different times, as long as they had the same elements. This is not so for properties created using newproperty: it requires exactly the same object as before in order to remember the mapping. A merely similar object will not do. (See HELP * EQUAL)

newproperty associates things compared using "=="

Newproperty requires a list, an integer representing the space allocated for the association table, the default value with which objects are associated, and a fourth argument that specifies how space will be reclaimed by the garbage collector, which for now we'll assume must be "perm", meaning that space will not be reclaimed, unless the whole property is. For further details (See HELP * NEWPROPERTY and REF * newproperty)

For example, here are several mappings created using newproperty, with table sizes 10, default values 0 or false.

    vars
        salary = newproperty([], 10, undef, "perm"),
        address = newproperty([], 10, undef, "perm");
We shall now again use lists to represent individuals, but this time we associate each list with a variable, so that later we can get at the very same list.

    vars
        john = [john smith],
        mary = [marylou walker];
We can then store salary and address information;

    15000 -> salary(john);
    25000 -> salary(mary);

    [room 3] -> address(john);
    [room 5] -> address(mary);
Now having set up the mappings we can ask for the information, using the value of the variable as input to the properties, e.g.:

    salary(john) =>
    ** 15000
    address(mary) =>
    ** [room 5]
But if we try to use new copies of the items with which the information is associated, we will not be able to drive the associations, because properties created with newproperty need the input to be "==" to the original, not merely "=" to it. Thus

    address([john smith]) =>
    ** undef
    salary([marylou walker]) =>
    ** undef
So it does not recognize the new inputs that are merely similar to the old. But if it is given exactly the same, identical input, it will be recognized:

    salary(mary) =>
    ** 25000
The difference occurs because, although the following is true:

    mary = [marylou walker] =>
    ** <true>
This one is not:

    mary == [marylou walker] =>
    ** <false>
The difference between properties created by newmapping and properties created by newproperty is that

    (a) the former are more general and flexible in their use
    (b) the latter are much more efficient in terms of time
The reason for (b) is that the use of "==" as a test is generally much faster than the use of "=".

Properties can be composed using <>, given to maplist, etc.

For example, using the mapping occupant, defined above, and maplist, we can find the occupants of rooms:

    maplist([[room 3][room 4][room 5][room 6]], occupant) =>
    ** [[john smith] <false> [bob walker] [ted bloggs]]
We can compose properties to find spouses of occupants:

    maplist([[room 3][room 4][room 5][room 6]], occupant <> spouse) =>
    ** [<false> <false> [mary low walker] <false>]
So only room 5 has an occupant whose spouse has been identified.



next up previous contents
Next: Exercise using properties Up: CHAPTER.4: PROCEDURES IN Previous: Arrays are procedures



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