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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,66423c08b54dd4a3 X-Google-Attributes: gid103376,public From: "Norman H. Cohen" Subject: Re: about abstract data types and pointer Date: 1996/09/24 Message-ID: <3247FEEC.37D2@watson.ibm.com> X-Deja-AN: 185049707 references: to: jk791840@er.uqam.ca cc: ncohen@watson content-type: text/plain; charset=us-ascii organization: IBM Thomas J. Watson Research Center mime-version: 1.0 reply-to: ncohen@watson.ibm.com newsgroups: comp.lang.ada x-mailer: Mozilla 3.0 (Win95; I) Date: 1996-09-24T00:00:00+00:00 List-Id: Benoit Rochefort wrote: > I use the ADA83 standard (but with the gnat compiler than can compile > ADA95). That's unfortunate, because most of your concerns are addressed in the Ada-95 revision. Since you have a compiler that compiles the current version of the language, why restrict yourself to the old version? > 1- Is there a way to define a procedure type like in MODULA-2 in > a way such: > > TYPE PROC IS PROCEDURE(IN E:ELEMENT); > > Or like in C where we can define a pointer to such a fonction? > (how can i define an access type in ADA that "points" to such > a procedure?) Yes. As in C, you use a pointer to the subprogram. (Pointers in Ada are called access values.) The syntax is: type Proc is access procedure (E: in Element); However, this feature is not available in Ada 83. In Ada 83 you must use generic templates or, if your compiler lets you, certain unportable hacks involving the manipulation of addresses. > Please don't suggest me to use a generic proc, because it's NOT > what i want; Map could be called for MANY procedures, not just one > for each instance of a List. example: > > Map(L, Put); -- Print each element on stdout. > Map(L, CountE); -- Count the number of elements (side effect). > Map(L, Draw); -- Draw the value of L on a graph. Sorry, too late, I already suggested it. ;-) But the objection you describe is not convincing. Once you write the template generic with procedure Map_One_Element (E: in Element); procedure Map (L: in List); you can create instances appropriate for each call site: procedure Put_Elements is new Map (Map_One_Element => Put); procedure Count_Elements is new Map (Map_One_Element => CountE); procedure Draw_Elements is new Map (Map_One_Element => Draw); You can even bundle the instantiation with the call by using a block statement: declare procedure Put_Elements is new Map (Map_One_Element => Put); begin Put_Elements (L); end; > Count could be written like this: > > FUNCTION Count(L: IN List) RETURN Natural IS ... > END Count; Well, you can't quite do THAT in Ada, since you declared Map as taking a procedure with a parameter of type List and NO result. (Modula-2 doesn't let you do that either.) But I presume that this inconsistency in your post was unintentional. > 2- Is there a way to totally hide the representation of an abstract > data type in the specification package? I really don't understand > why we should specify the representation of such a type in the > PRIVATE part of the specification package (except for compiler > needs -- that is simpler for the compiler :-) ). It's an efficiency issue. After the package specification is compiled, clients of the package specification can be efficiently compiled, even before the package body is compiled. For example, a client might contain an assignment statement copying a value of the private type. If the compiler can deduce the length of the value from the full declaration in the private part of the package specification, it can choose an appropriate machine instruction. However, if the definition of the data structure in the private part of the package specification bothers you, you can declare a private type to be implemented as a pointer to some type whose declaration is deferred to the package body: package P is type T is private; ... private type T_Node; -- Incomplete declaration type T is access T_Node; end P; package body P is type T_Node is ...; -- Full declaration ... end P; Both Ada 83 and Ada 95 allow you to defer the full declaration of T in this way. The mechanism is identical to the Modula-2 opaque type. The only difference is that Ada gives you the choice between fastidiousness about the aesthetics of data abstraction and saving the cost of an extra level of pointer indirection. > 3- Is there a way to "add" or change attributes to a new type that i > have elaborated as an abstract data type (in a package). > > Ex: L'First could have another meaning here if L is a List. > List'Nb could denote the number of elements of a List L. > > I know i can (and sure i must) code these as functions but i just > want to use them as attribute; which could be much more natural here. Sorry, you have to use the function-call notation (which I find every bit as natural). > Is that what RENAMES is for? No, you can rename certain attributes as functions, but you can't do the opposite. > 4- Is there a way to overload the ":=" operator if List is a > limited private type? > > ex: > > L1 := L2; > > could make a copy of all elements of L1 into L2. This is much more > natural than > > Copy(L1, L2); In Ada 83 you just write the Copy procedure and live with the slightly less natural notation. In Ada 95, you declare list to be a nonlimited "controlled type" (i.e., a type derived from the type Ada.Finalization.Controlled) and override its Adjust procedure. This is a procedure automatically invoked with the target object of an assignment just after the assignment takes place. In your example, the overriding version of Adjust would replace the pointer that the assignment copied into a List object with a pointer to a pure copy of the list created by the procedure. > 5- Do the ADA83 standard specify that the deallocation of memory is > automatically done? Or must I ensure that my program does it? > > ex: > > PROCEDURE Test IS > L: List; > BEGIN > Add(L, 3); > Add(L, 4); > END Test; > > If L is a pointer to some NEW element created; will it be freed > automaticaly on return of the PROCEDURE Test? Or must i provide > an operation to free memory (like Dispose)? Both Ada 83 and Ada 95 explicitly ALLOW automatic garbage collection, but do not require it. No Ada-83 compiler supports it, and neither does GNAT, but Ada-95 compilers targeted to the Java virtual machine do. Ada-95 controlled types provide essentially the same functionality as C++ destructors. In addition to the Adjust procedure I already described, there is a Finalize procedure that can be overridden when the type Ada.Finalization.Controlled is extended. It is invoked automatically just before an object is about to cease to exist. In the example above, L ceases to exist upon return from Test, so just before Test returns, the Finalize procedure for type List is invoked with L as a parameter. This version of Finalize would traverse the list and free every cell (or perhaps just decrement a reference count that Adjust increments, and free the list cells when the reference count falls to zero). > 6- Now the easy one. > Is there a function or procedure to read a character on the > keyboard without the need to press enter WHICH IS DEFINED ON THE > STANDARD (independant of the used compiler and machine). Again, there is no standard mechanism in Ada 83. Ada 95 provides the procedure Ada.Text_IO.Get_Immediate for this purpose. (This procedure was not fully supported in early releases of GNAT, but I believe it has been supported in more recent releases.) -- Norman H. Cohen mailto:ncohen@watson.ibm.com http://www.research.ibm.com/people/n/ncohen