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!mailrus!purdue!rjh From: rjh@cs.purdue.EDU (Bob Hathaway) Newsgroups: comp.lang.ada Subject: Re: Procedure types and dynamic binding Message-ID: <5816@medusa.cs.purdue.edu> Date: 11 Jan 89 02:08:45 GMT References: <5806@medusa.cs.purdue.edu> <4058@hubcap.UUCP> Sender: news@cs.purdue.EDU Reply-To: rjh@cs.purdue.edu (Bob Hathaway) Organization: Department of Computer Science, Purdue University List-Id: > Another more direct way to parameterize a change operation is > to use a procedural variable as a parameter. Such as: > > generic > type ELEMENT_TYPE is private; > package ... > type PRINT_PROCEDURE is procedure (ELEMENT : in ELEMENT_TYPE); > procedure CHANGE_PRINT_OPERATION (PRINT_OPERATION : in PRINT_PROCEDURE); > > This allows dynamic specification of statically checked print procedures per > instance while the previous example assumed the user knew all allowable > procedures during instantiation. > But now we have a highly changeable system. What I am asking is, > "Is there any reason we need this extremely high level of changeability?" > I think the answer is yes, and I'll provide a summary of the method under discussion instead of another example. As I mentioned to Bill about a month ago, I have been working on a generic class structure for about a year. Other simpler languages have emerged and provided classes but I am not aware of any extending the idea with generics. If Ada is to continue remaining viable as a state-of-the-art programming language then incremental extensions such as procedural variables and generic classes are necessary. Ada is often considered a general purpose programming language, a systems programming language, and an object-oriented programming language and its use has far surpassed its original intention. Grady Booch has presented an elegant object-oriented design strategy for Ada and since most programmers are using this style of programming, Ada should be extended to provide first class constructs supporting this methodology. Classes provide an incremental improvement in abstract data types and together with procedural variables they provide an elegant solution to parameterized operations. I owe some credit to Chris Torek, who posted a method for "the right way to do object oriented programming in C" (his words as I remember) by storing data and operations together. I extended his idea with dynamically parameterized operations in Adts as the need arose and am sure one "right way to do this" is in Ada with generics. Again, the presented example of procedural variables allows abstract data types to dynamically (at runtime) alter thier operations so each instance can be individually parameterized with an appropriate subprogram to perform that operation. Previous postings presented other uses as well. The first posted example used type inference and provided a method to specify all allowable subprogram invocations per instance during instantiation. This method insures controlled operations during and after instantiation and the Adt state will not be hard to trace. The second method allows Adt operations to be dynamically parameterized during and after instantiation and can be used as the need arises. A history can be kept within the Adt for mission critical applications or complex debugging. I will let the method stand on its own merits and it has been my experience that parameterized operations are frequently an appropriate solution. Here is a simple example of parameterization via procedural variables using a single operation Adt: generic type ELEMENT_TYPE is limited private; package STACK is type ADT is limited private; type OPERATION_TYPE is procedure (ELEMENT : in out ELEMENT_TYPE); procedure OPERATION (INSTANCE : in out ADT; ELEMENT : in out ELEMENT_TYPE); procedure CHANGE_OPERATION (INSTANCE : in out ADT; NEW_OPERATION : in OPERATION_TYPE); end STACK; or generic type ELEMENT_TYPE is limited private; package STACK is type ADT is limited private; procedure OPERATION (INSTANCE : in out ADT; ELEMENT : in out ELEMENT_TYPE); generic with procedure NEW_OPERATION (ELEMENT : in out ELEMENT_TYPE); procedure CHANGE_OPERATION (INSTANCE : in out ADT); end STACK; Here is a recommended class based approach: generic type ELEMENT_TYPE is limited private; class type OPERATION_TYPE is procedure (ELEMENT : in out ELEMENT_TYPE); procedure OPERATION (ELEMENT : in out ELEMENT_TYPE); procedure CHANGE_OPERATION (NEW_OPERATION : in OPERATION_TYPE); procedure INITIALIZE; -- These can be dynamically parameterized, if desired procedure FINISH; -- or declared in the private part. -- exception declarations -- private pragma NO_ENTRY; -- If Bill wants to call these explicitly pragma NO_EXIT; on entry INITIALIZE; on exit FINISH; end STACK; The reader is referred to previous articles for discussions on more powerful parameter passing mechanisms which require a runtime type system. Here is an example within a class construct: class STACK is type OPERATION_TYPE is procedure (ELEMENT : polymorphic); procedure OPERATION (ELEMENT : in polymorphic); procedure CHANGE_OPERATION (NEW_OPERATION : OPERATION_TYPE); function GET_OBJECT return polymorphic; end STACK; class body STACK -- see previous class example. end STACK; And here is an example of Bill's proposal with unrestricted pointers (*If* unrestricted pointers can to apply to subprograms): class STACK is type OPERATION_TYPE is procedure; procedure OPERATION (ELEMENT : in polymorphic;...); procedure CHANGE_OPERATION (NEW_OPERATION : OPERATION_TYPE); function GET_OBJECT return polymorphic; end STACK; But this last method requires considerable thought. I'll assume any procedure can be passed to CHANGE_OPERATION and calls to OPERATION will require runtime elaboration. All packages assign the new operation to an internal procedural variable. As shown above, generics co-exist with procedural variables. Another issue is default parameters; what if the supplied procedure doesn't have the same default parameters? The simplist solution is to enforce a new rule, such as during assignment of a subprogram to a procedural variable any default parameters in the procedural variables parameter structure must be matched by corresponding default parameters in the supplied subprogram. But for now I'll assume assignment is legal as long as subsequent invocations of the procedural variable don't reference default parameters not supplied by the subprogram. Such cases should be avoided, however. I will let the idea stand on its own merits for now since there is time for consideration before the next extension. Is there any way to get feedback or proposal information for the Ada 9X extension? I think there have been several worthwhile ideas presented so far. Bob Hathaway rjh@apurdue.edu