From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=BAYES_00,INVALID_DATE, MSGID_SHORT,REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!attcan!uunet!lll-winken!ames!ncar!boulder!sunybcs!rutgers!gatech!hubcap!billwolf From: billwolf@hubcap.clemson.edu (William Thomas Wolfe,2847,) Newsgroups: comp.lang.ada Subject: Re: Procedure types and dynamic binding Message-ID: <4046@hubcap.UUCP> Date: 9 Jan 89 01:47:50 GMT References: <5796@medusa.cs.purdue.edu> Sender: news@hubcap.UUCP Reply-To: wtwolfe@hubcap.clemson.edu List-Id: >From article <5796@medusa.cs.purdue.edu>, by rjh@cs.purdue.EDU (Bob Hathaway): >> [Discussion of unrestricted pointers] > > Do you mean passing unrestricted pointers to procedures and then > selecting the procedure via overloading (ad-hoc polymorphism) at runtime? > I meant allowing polymorphic parameters to a particular subprogram, > such as > procedure test (parameter : polymorphic; ...) is ... Yes, that's what I had in mind, although I would also provide procedure INSERT_ITEM (TARGETED_STACK : in out STACK; NEW_ITEM : in OBJECT); to avoid making the user set up a pointer just to get a parameter passed. The resulting situation would be the same as if an unrestricted pointer had been used and POINTER.all had been made to serve the same function. > [An extended example of toggling between two print procedures] > > procedure MAKE_SHORT_PRINT (); -- sets PRINT up to call SHORT_PRINT, > -- a user-supplied generic parameter > > procedure MAKE_LONG_PRINT (); -- sets PRINT up to call LONG_PRINT, > -- a user-supplied generic parameter > > procedure PRINT (); -- a service provided to the user > Now, a call to print an instance of this class will at first result in > invocation of the SHORT_PRINT parameter. But programmers can make > subsequent calls to PRINT for this instance use long_print > through a call to MAKE_LONG_PRINT. Each instance can parameterize > its print subprogram to output its data as desired. Other tricks > could be used but this method avoids the use of case statements and > is a simple use of procedural variables. > In more complicated examples parameterizable operations for each Adt > instance could simplify the program considerably, such as by avoiding > nested case statements. But you've designed your ADT to handle only two types of printing situations: SHORT_PRINT and LONG_PRINT (or at least this would seem to be the case to anyone who takes your generic parameter structure at face value). What we REALLY want is for ANY type of printing operation to occur, depending on the user's needs, which we cannot forecast in advance. But now look at the trap we've walked into: we must provide MAKE_*_PRINT, where * represents an indefinite set of cases. We now see that our old friend, the case statement, is not gone; it has simply taken on a new form. Verdict: a bad ADT design idea. Now let us step back for a moment and consider our situation. We wish to accept a PRINT procedure from our user, which we will use in the course of printing out the contents of the stack. But how do we know that the method we choose for encapsulating the stacked objects in the printout will make our user happy? Perhaps our idea is to print each object, separated by a blank line, but our user wants to see each object surrounded by a rectangular box of :-)s... We now see that our entire approach to the problem is wrong. We must provide a method whereby our user can access his/her stacked objects, and allow the user to implement any arbitrary print procedure. But, you object, the user must be given some sort of standard print procedure which can be used as a default! And so he/she must; we achieve this by supplying in a utilities package the following: with TEXT_IO; generic type DATA_STRUCTURE is limited private; type STORED_OBJECT is limited private; with procedure NEXT_POSITION (STRUCTURE : in out DATA_STRUCTURE); with function GET_CURRENT_ITEM (STRUCTURE : in DATA_STRUCTURE) return STORED_OBJECT; with procedure PRINT (TO_FILE : in TEXT_IO.FILE_TYPE; THE_ITEM : in STORED_OBJECT ); procedure STANDARD_PRINT_ROUTINE (INTO_FILE : in TEXT_IO.FILE_TYPE; STRUCTURE : in DATA_STRUCTURE); Our user is now provided with maximal power and convenience. Note that the above utility applies to any class of structures for which the user can construct a procedure to sequentially access every stored object in some user-defined order. Still waiting for a situation in which procedural variables should be used in order to formulate an intuitively natural solution... Bill Wolfe wtwolfe@hubcap.clemson.edu