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.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,a8985ede8fe3d111 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1994-10-05 10:38:59 PST Newsgroups: comp.lang.ada Path: bga.com!news.sprintlink.net!howland.reston.ans.net!noc.near.net!inmet!dsd!stt From: stt@dsd.camb.inmet.com (Tucker Taft) Subject: Re: Is Ada the future? [was: Is C++ the future?] Message-ID: Sender: news@inmet.camb.inmet.com Organization: Intermetrics, Inc. References: <36q7m5$4ef@Starbase.NeoSoft.COM> Date: Wed, 5 Oct 1994 13:49:04 GMT Date: 1994-10-05T13:49:04+00:00 List-Id: In article , John DiCamillo wrote: > ... >Oh, and thank you for the references yesterday. >I'm preparing a rebuttal to the 9x-cplus paper, >but I need some clarification on Ada 9x first: > >How does polymorphism (dynamic dispatch) work >in Ada 9x? Here is the short form: If the controlling operand(s) of a call on a primitive subprogram are class-wide, then the tag of the operand(s) determine which body of the subprogram is executed. Here is an attempt at a translation into English: In Ada 9X, one distinguishes explicitly between objects of a "specific" type (denoted by a simple type name like "T"), and objects of a class-wide type (denoted by a name like "T'Class"). This explicit distinction helps the programmer understand and control where dynamic binding is occurring. Class-wide types essentially represent a set of types, in particular, the class-wide type T'Class represents T and all types derived from T, directly or indirectly (this set of types is also called the "class of types rooted at T"). If you don't use class-wide types anywhere in your program, then all binding is static. The only time you get dynamic binding is when you have a class-wide object (usually a parameter of a type like T'Class, or an object designated by a pointer to a type like T'Class), and you pass it to one of the "primitive" operations of its corresponding specific type (e.g. of the type T). The primitive operations of a type T are those operations defined immediately within the same package spec as T itself, and that have parameters or a result of the specific type T. The primitive operations of a type are inherited by any derivative of T; they may be overridden if desired. Here is an example: package P is type T is tagged private; -- T is the root of the class T'Class function Image(X : T; Min_Width : Natural := 0) return String; -- Image is a "primitive" op of T function Combine(X, Y : T) return T; -- Combine is another primitive of T ... type T2 is new T with private; -- derive T2 from T; -- T2 is the root of the (sub)class T2'Class function Combine(X, Y : T2) return T2; -- overrides inherited Combine function -- inherits as is: -- function Image(X : T2; Min_Width : Natural:=0) return String; procedure Break_Up(A : T2; B, C : out T2); -- This is an additional primitive op of type T2 end P; I can now pass operands of type T to the Image and Combine operations of type T, and operands of type T2 to the Image, Combine, and Break_Up operations of type T2. Such calls would all use static binding. I could alternatively define an operation which took a parameter of any type in the class rooted at T, and then used dynamic binding to call the "appropriate" implementation of any primitive of T, based on a run-time tag carried along with the class-wide operand. For example: procedure Put(Q : T'Class) is -- Take an object of any type in class rooted at T begin -- Use dynamic binding to call the "appropriate" Image function Text_IO.Put(Image(Q)); end Put; >Is Ada Covariant, Contravariant, or Invariant? When an operation is inherited by a type T2 from a type T, the new inherited operation is covariant in all operands and result that are of the specific type T, meaning that all the types of such operands and result become T2, as illustrated above for Combine and Image. This works quite well for binary and n-ary operations, and illustrates one of the advantages of treating "controlling" operands symmetrically. In Ada 9X there is no need to pull out one of the parameters to the "prefix" position of the call, such as "Z := X.Combine(Y);". You simply write, as in Ada 83, "Z := Combine(X, Y);". >Could someone please explain "generic derived >types and generic formal packages" and how >they are different than C++ templates? An Ada generic unit is very similar to a C++ template. A "generic derived type" and a "generic formal package" are simply differnt kinds of generic formal parameters. There are 4 basic kinds of generic formal parameters: Formal Types, Formal Objects, Formal Subprograms, and Formal Packages. That means you can parameterize a generic unit by any one of these four kinds of things. Unlike in C++, the semantic correctness of a generic unit is checked when it is compiled, rather than only when it is instantiated. This means that the formal parameters of a generic must carry more information, to indicate to the compiler (and to the potential user of the generic ;-) what kinds of features the actual types, objects, subprograms, or packages, must have. For example, one can declare a given formal type as being a "discrete" type, which means that the actual type must be an integer or enumeration type. Inside the generic unit you may only use operations that are available on all discrete types, such as 'Image, 'Pred, 'Pos, assignment, equality, relationals, etc. In any case, to answer your original question, for a formal type that is declared to be a "generic formal derived type," the actual type must be any type descended from the ancestor specified in the formal derived type declaration. For a "formal package," the actual must be any instance of the generic package identified in the declaration of the formal package. In any case, I highly recommend you down-load and read the intro to Ada 9X, available on ajpo.sei.cmu.edu in public/ada9x/reports/intro, in several popular formats (e.g. Word, WordPerfect, RTF, ASCII, etc.). It is quite short, and covers the above features in a much more organized fashion than the above. Perhaps even better, try GNAT (the GNU-based Ada 9X compiler, available by FTP from cs.nyu.edu and elsewhere). It is hopeless to evaluate a language fully without taking it out for a spin... > John DiCamillo Pinin' for the fjords? > milod@netcom.com What kind of talk is that? -Tucker Taft stt@inmet.com Intermetrics, Inc.