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.
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]
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 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]) => ** undefSo 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) => ** 25000The 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 timeThe reason for (b) is that the use of "==" as a test is generally much faster than the use of "=".
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.