Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!usc!apple!snorkelwacker.mit.edu!bloom-beacon!eru!hagbard!sunic!mcsun!ukc!icdoc!syma!aarons From: aarons@syma.sussex.ac.uk (Aaron Sloman) Newsgroups: comp.object Subject: Re-use and functions as data (Was: Examples of Multiple Inheritance) Summary: Some benefits of OOP come from having functions as data Keywords: OOP, Reuse and languages with functions as first class objects Message-ID: <4040@syma.sussex.ac.uk> Date: 16 Dec 90 12:10:33 GMT References: <60700005@inmet> <980@culhua.prg.ox.ac.uk> <17562@neptune.inf.ethz.ch> <743@puck.mrcu> <1056@tetrauk.UUCP> Organization: School of Cognitive & Computing Sciences, Sussex Univ. UK Lines: 147 > > (Paul Johnson) writes: > >....If you have fully analysed your > >problem and know what routines are to be called where then you can > >code in Pascal or C just as easily. > rick@tetrauk.UUCP (Rick Jones) writes: > Organization: Tetra Ltd., Maidenhead, UK [...portion omitted...] > ....There are lots of > ways to produce a structured solution to a _specific_ problem; object > orientation is just one way to do it. But that doesn't make your system more > resilient to change, which is the real point. > > The most important point about reuse is the ability to reuse something in a way > that was not anticipated when it was written. Rigid hierarchies don't stand > much chance of letting you do that. [...portion omitted...] > > In a function oriented system, reuse is provided by function libraries. These > work quite well, but we all know that they are limited in scope because of > problems of encapsulation and extension. The acclaimed benefit of object > oriented methods is better reusability. [...portion omitted...] > > I feel this concern about MI is all to do with implementation problems of > languages which have been (short-sightedly) designed without due consideration > for the ultimately essential support of multiple inheritance. Many languages do have restrictions of this sort. However, some (though probably not all) of the facilitation of re-use that comes from OO Languages can also be achieved by languages that allow procedures to create functions and return them as results that can be used as input to other procedures that call them, e.g. by applying them to approriate data. This sort of facility is provided by Scheme, Common Lisp, Pop-11 (A Lisp-like language with a Pascal-like syntax that many find more readable), ML, and others. One requirement for this is either a polymorphic type mechanism (as in ML) or the ability to postpone type-checking till run time as in the other languages, which therefore provide greater flexibility. A toy example, to illustrate: suppose you want to have a re-usable function -create_pairs- that takes in two lists of objects (of any type), a function that creates two-element records, with one object from each list, and then makes and returns a sorted list of the two element records, where the required ordering of the sorted list depends on the types of objects in the list, etc. (How would you do this in an OO Language?). In Pop-11 you could define this as follows define create_pairs(list1, list2, makepair, testbefore) -> list; lvars item1, item2, list1, list2, procedure makepair, /* the pair creator */ procedure testbefore, /* the sort predicate */ list; /* make the unsorted list and assign it to list */ [% for item1, item2 in list1, list2 do makepair(item1, item2) endfor %] -> list; /* sort it, using the the library -syssort- and the supplied predicate */ syssort(list, testbefore) -> list enddefine; For example, given two lists of numbers, create a list of pairs of numbers, sorted by the sum of the pairs. vars numbers1 = [12 14 16 18], numbers2 = [28 25 22 19]; Assuming the pairs have been created using the system procedure -conspair- and can therefore be accessed using -front- and -back-, define the ordering predicate. define pairbefore(pair1, pair2) -> boolean; /* true iff sum of elements in pair <= those in second */ lvars pair1, pair2, boolean; front(pair1) + back(pair1) <= front(pair2) + back(pair2) -> boolean enddefine; /*Test create_pairs and print out the result */ create_pairs(numbers1, numbers2, conspair, pairbefore) => ** [[18|19] [16|22] [14|25] [12|28]] (This example does not use the most efficient coding). Note that this procedure can be applied to lists containing any type of data, provided that an appropriate pair creating and pair ordering procedure are available. I.e. The procedure -create_pairs- is re-usable for many different sorts of data-types, whose existence need not have been anticipated by the author. Re-use can be further simplified by using "properties" to associate with each type of entity, or each pair of types, the appropriate pair-creating and pair-comparing procedures. Then the create_pairs procedure would not need to be given the last two procedural arguments explicitly. It would use the contents of the first two arguments to get the appropriate procedures from the properties. A program (or development team) that dynamically created new types of data, and dynamically created appropriate functions for creating pairs and ordering them, and stored those functions in the appropriate properties, could use create_pairs on lists of objects of types that were not anticipated by the original programmer, in accordance with Rick's comment: > The most important point about reuse is the ability to reuse > something in a way that was not anticipated when it was written. Here, though, instead of information having to be associated with each type of object we allow extendable information to be associated with a particular generic procedure: via the two extendable properties. OO languages provide support for this through inheritance mechanisms. But there are other ways, as I hope my rather simple and artificial example illustrates. It should be clear how far more sophisticated examples could use the same technique, e.g. a re-usable network matching program for networks of various sorts, a re-usable database manager for storting data of different sorts, etc. This is common practice among Pop-11 programmers (as the -syssort- library program used in the example, illustrates, although the present version requires the user to specify the ordering predicate rather than associating one ordering predicate with each type of object, which would be rather restrictive). (However, because some users prefer to have an explicit OOP approach, including multiple inheritance, etc., Poplog Pop-11 now also includes an optional language extension to support it.) Aaron Sloman, School of Cognitive and Computing Sciences, Univ of Sussex, Brighton, BN1 9QH, England EMAIL aarons@cogs.sussex.ac.uk