37.2.3 Generic Objects for Easy Reuse

Defining objects for easy reuse is a very important property for reducing the cost of large projects. One important technique is to define prototypes in a parameterized way, so that various instantiations of a prototype correspond to different uses. Parameterized or generic objects have been used for this purpose in other object-oriented systems. An object-identifier can be a compound term. The arguments of the term are parameters that are visible in the object-body. Here we show one example. Other examples and techniques that use this facility has been investigated extensively in [McCabe 92].

The following is an object sort that sorts lists of different types. sort has a parameter that defines the type of the elements of the list. Notice that Type is visible to all methods in the body of sort, and is used in the method partition/4. In the query, we use sort(rat) to sort a list of terms denoting rational numbers. We must therefore define a rat object and its < method also:

     rat :: {
             (P/Q < R/S) :- :(P*S < Q*R)
             }.
     
     sort(Type) :: {
             :- :use_module(library(lists), [append/3]) &
     
             qsort([], []) &
             qsort([P|L], S) :-
                     partition(L, P, Small, Large),
                     qsort(Small, S0),
                     qsort(Large, S1),
                     :append(S0, [P|S1], S) &
     
             partition([], _P, [], []) &
             partition([X|L1], P, Small, Large) :-
                     (   Type :: (X < P) ->
                         Small = [X|Small1], Large = Large1
                     ;   Small = Small1, Large = [X|Large1]
                     ),
                     partition(L1, P, Small1, Large1)
             }.
     
     | ?- sort(rat) :: qsort([23/3, 34/11, 45/17], L).
     
     L = [45/17,34/11,23/3]

Parameterized objects are interesting in their own right in Prolog even if one is not interested in the object-oriented paradigm. They provide global context variables in a Prolog program without having to add such variables as additional context arguments to each clause that potentially uses the context.