This section is best omitted by beginners.
Notice that in Pop-11 (like Lisp) a procedure like member (or iselement) can be defined to take any sort of object and any sort of list of objects. In a `typed' language like Pascal you would have to define one version of the procedure for lists of numbers, another for lists of words, another for lists of lists, etc. This kind of generality is one of the things that gives Pop-11 its power.
Another example is the library procedure syssort. This takes a list and an ordering predicate, and returns a copy of the list that has been sorted according to the ordering predicate. For example, this will sort a list of words or strings alphabetically:
syssort([the cat sat on the mat], alphabefore) => ** [cat mat on sat the the]One can define a predicate that orders two lists L1 and L2 according to whether the second item of L1 is alphabetically earlier than the second item of L2.
define second_first(list1, list2) -> boole; if list1(2) < list2(2) then true else false endif -> boole enddefine;or more concisely
define second_first(list1, list2); alphabefore( list1(2), list2(2) ) enddefine;We can use this ordering predicate to sort a list of lists:
syssort([[a d] [c a] [e b] [f c]], second_first) => ** [[c a] [e b] [f c] [a d]]syssort is an example of a second order procedure, since one of its arguments is a procedure, which it uses internally. It is very general because it can be applied to many different combinations of types of lists and ordering procedures. syssort is a type-less procedure: it can only be applied to a list and a procedure, but the list can contain objects of any type, and the procedure can be of any type that is suitable for the elements of the list. It is even possible to have a list of elements of different types, provided that the ordering procedure imposes a suitable ordering on them.
This is a small example of the sort of power and modularity that comes from using a language that treats procedures as objects that can be given to other procedures, and which does not require all type information to be available when a procedure is defined. Higher order programming of this kind can make software development and maintenance more effective because the same procedure can be re-used in many different contexts.
It might be thought that this freedom from type restrictions makes Pop-11 an unsafe language: the answer is that the types are checked at run time instead of compile time. The second argument that is given to syssort will check that the elements of the list are of the right type. If the types are wrong, an error message is produced.
;;; This will make alphabefore complain because it gets a number syssort([ 21 4 3 55 22], alphabefore) => ;;; MISHAP - STRING NEEDED ;;; INVOLVING: 21 ;;; DOING : alphabefore get_run syssort ....Sometimes it is easier to produce bug-free programs if the type checking is postponed till run time than if very complex checking is done at compile time and then a compiled program is produced that is ASSUMED to be safe to run. In some cases the assumption may turn out wrong. Ruling that out can make a language extremely restrictive and inflexible to use for complex software.
In the next chapter we shall give a somewhat more formal introduction to Pop-11, defining in more general terms some of the constructs illustrated here.
First here's a simplified overview of the Pop-11 virtual machine.