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!husc6!purdue!rjh From: rjh@cs.purdue.EDU (Bob Hathaway) Newsgroups: comp.lang.ada Subject: Re: Procedure types and dynamic binding Message-ID: <5793@medusa.cs.purdue.edu> Date: 8 Jan 89 01:49:45 GMT References: <5790@medusa.cs.purdue.edu> <4037@hubcap.UUCP> Sender: news@cs.purdue.EDU Reply-To: rjh@cs.purdue.edu (Bob Hathaway) Organization: Department of Computer Science, Purdue University List-Id: >> Yes, class structures with generics would provide good data abstraction. >> This would allow classes to be statically parameterized by types, variables, >> constants, and subprograms. Generics are good for setting an Adt once, >> such as >> a stack which is parameterized by its element type and a print subprogram. >> But what about dynamic parameterization? For dynamic parameterization of >> data, >> polymorphic parameters to Adt operations are needed to allow the greatest >> expressiveness. An example is a stack of any element type which could be >> provided by polymorphic parameters to an insert subprogram. For dynamic >> parameterization of operations, procedural variables are needed. > > No, all we need is the ability to have pointers which are not bound > to any specific type. Most of the time we want to say "pointer to > SPECIFIC_TYPE", but sometimes we just want to say "pointer". Given > the ability to specify an unrestricted pointer, we can implement > the desired stack (or whatever) of any element type. But this assumes no type or error checking at all. By dynamic parameterization I meant with runtime type and error checking. For static typechecking of data we can use a pointer to a tagged variant record to distinguish types. This assumes foreknowledge of the types in the variant but at least allows subprograms to distinguish objects. With unbound pointers, there is no built-in type or error checking mechanism. This covers the case of "pseudo" polymorphic parameters but what about dynamically parameterized operations? Ada has an address type applicable to function and task type addresses but this is implementation dependent and there is no defined typechecking mechanism for the subprogram parameter structure as there is with procedural variables. Unbound pointers to functions have the same consequences. While tasks can allow procedural abstraction, better is a higher order construct such as procedural variables. >> >> Now, adding polymorphic parameters to Ada would be a sizable extension > > Not true; all we need to do is write procedures which require an > arbitrary pointer as a parameter, and we're done. I meant with runtime typechecking and how this should be done is another point. Milner's type system uses static typechecking for polymorphic parameters but doesn't seem to provide the necessary power for arbitrary polymorphism. More powerful is a scheme which invokes operations on arbitrary types at runtime with dynamic type and error checking mechanisms and not just simple statically checked invocation. This requires a more elaborate mechanism but adding polymorphism to Ada's static type system would allow programmers to fully specify types for static checking and efficiency or choose a more powerful parameter passing mechanism for greater expressiveness however polymorphic parameters and variables would entail major changes to the LRM. On dynamically parameterized operations, if incremental improvement is the goal of the Ada-9X standard then simple statically checked dynamically parameterized operations can be provided with procedural variables. Dynamic typechecking of procedural variables is also possible but I was advocating statically checked procedural variables as an extension. ># But the ># flexibility of dynamic parameterization allows maximum expressiveness ># and greater power, and so "the burden of proof" has to be made against ># dynamically parameterized operations. Since static generics and dynamic ># parameterization are not mutually exclusive, both could be provided. > > Unless, as I have shown above, a simpler mechanism will suffice. But this "proof" doesn't apply to dynamically parameterized operations with type and error checking as defined above, could you comment on that also? >#>> What if variables of type Tree_Type should >#>> be traversed in different ways depending on context? >#> >#> Just make basic traversal operations a part of your abstraction. >#> > > But this calls for case statements throughout the program to determine which ># operation to call, as mentioned above. For maximum expressiveness, I might ># want to set instances with particular traversal operations and then use a ># single operation invocation at a later point in the program which will invoke ># the correct operation for all instances, reducing redundant code and allowing ># maximum expressiveness. > > Using the above mechanism, we've eliminated the case statements. > I'm not sure what this means. With pointers to functions there should be typechecking of parameter structures and this is the essence of procedural variables. > Now set up your abstraction to provide a "current node" concept, > along with operations like DESCEND_LEFT, DESCEND_RIGHT, and ASCEND. > This can be implemented either via parent pointers or via a secret > stack which holds the path of descent used to reach the current node. > Yes this would work, but leaves programmers to build their own traversal routines. My idea was to provide a mechanism allowing programmers to specify a procedural invocation in a single, simple statement and have the Adt select and carry out the operation implicitly. Bob Hathaway rjh@purdue.edu