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, T_FILL_THIS_FORM_SHORT 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: mheaney@ni.net (Matthew Heaney) Subject: Re: about abstract data types and pointer Date: 1996/09/24 Message-ID: X-Deja-AN: 185198372 distribution: world references: content-type: text/plain; charset=ISO-8859-1 organization: Estormza Software mime-version: 1.0 newsgroups: comp.lang.ada Date: 1996-09-24T00:00:00+00:00 List-Id: In article , jk791840@er.uqam.ca wrote: >Reposting article removed by rogue canceller. > >Hi! I'm new with ADA but i'm a programmer since a long time. Ada is not an acronym, thus you need not capitalize its name. The language was named in honor of Ada Loveless, the assistant of Charles Babbage, and the world's first programmer. > >I use the ADA83 standard (but with the gnat compiler than can compile >ADA95). > >I have some questions to start with: > >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?) (Note that my Ada 95 syntax is a little shaky...) type Procedure_Access is access procedure (E : in Element); For example, procedure Process (The_Element : in Element); PA : Procedure_Access := Process'Access; To invoke procedure Process through the access object: E : Element := ...; PA (E); > This would be very helpful in the case of a list type (for example), > having an operation defined like that: > > PROCEDURE Map(L: IN List; P: PROC); > > Which map the P Procedure to each element of the list. P would > obviously cause a side effect (like printing an element). > > OR can I define procedure Map something like that: > > PROCEDURE Map(L: IN List; P: PROCEDURE(IN ELEMENT)); > > Please tell me how i can call the p procedure passed as a parameter > to Map in the code; maybe something like: type List is private; type Procedure_Access is access procedure (E : in Element); procedure Map (L : in List; P : in Procedure_Access); > > P(E); That is how you call the actual argument P, in fact. > 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. > > Of course; Draw and Put have the side effect of "writing". procedure Put (E : Element); procedure CountE (E: Element); procedure Draw (E : Element); L : List; Map (L, Put'Access); Map (L, CountE'Access); Map (L, Draw'Access); > > Count could be written like this: > > FUNCTION Count(L: IN List) RETURN Natural IS > Nb : Natural := 0; > PROCEDURE CountE IS > BEGIN > Nb := Nb + 1; > END CountE; > BEGIN > Map(L, CountE); > RETURN Nb; > END Count; I'm not sure about the exact legality rules for doing this. Either Map (L, CountE'Access); is allowed, or if not, then Map (L, Count'Unchecked_Access); for use when you know something about the lifetime of the subprogram you're accessing that the compiler doesn't. >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 :-) ). Even in C we > can hide the representation of an abstract data type from the > header file. Why not in ADA which is supposed to be better for > the information hiding principle? Well, I'm not sure what you mean there about C. For example, in C I might do typedef struct StackRep* Stack; to declare a _pointer_ to stack in the header, and hide the representation of its structure in the body. That's a bit different from what you said, though. And yes, you can so the same thing in Ada: package Stacks is type Stack is private; ... private type Stack_Representation; type Stack is access Stack_Representation; end Stacks; This allows one to defer the implementation of the Stack_Representation to the package body. However, this is an probably an improper use of access types. One should use access types because the abstraction itself requires reference rather than value semantics. To implement an abstract data type as an access type to _really_ hide the representation is a not such a great idea (at least in Ada 83), because of all the attendant problems one has with memory leaks. And no, putting the representation in the private region of the specification does *not* violate information hiding (nor does it violate information hiding in C++ or Eiffel or...). Information hiding does not mean where the full view of the type appears (I could just read the body in that case), but rather how clients are able to manipulate the abstraction. >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. None that I know of (though I think it's a good idea). The only attributes I think you can change in Ada 95 are the T'Input and T'Output, for use with Streams_IO. > > 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. > > Is that what RENAMES is for? A great technique that should be in every Ada programmer's arsenal! It's Ada's alias feature. For example, I can rename elements of a record if the dot notation gets out of hand: package Bounded_Stacks is type Stack (Max_Depth : Positive) is limited private; procedure Push (The_Item : in Item; On : in out Stack); private type Item_Array is array (Positive range <>) of Item; type Stack (Max_Depth : Positive) is record The_Items : Item_Array (1 .. Max_Depth); The_Depth : Natural := 0; end record; end Bounded_Stacks; ... procedure Push (The_Item : in Item; On : in out Stack) is The_Stack : Stack renames On; -- gives The_Stack a better name than "On" The_Depth : Natural renames The_Stack.The_Depth; begin The_Depth := The_Depth + 1; The_Stack.The_Items (The_Depth) := The_Item; end; compare that to this procedure Push (The_Item : in Item; On : in out Stack) is begin On.The_Depth := On.The_Depth + 1; On.The_Items (On.The_Depth) := The_Item; end; So you can rename objects. But you can also rename subprograms with Bounded_Stacks; package P is function Push (The_Item : in Item; On : in out Stack) renames Bounded_Stacks.Push; and rename exceptions (or any other object, really) with IO_Exceptions; package Text_IO is type File_Type is limited private; ... Use_Error : exception renames IO_Exceptions.Use_Error; end; You can even rename a task entry as a procedure: task T is entry E (The_Item : in Item); end T; procedure Put (The_Item : in Item) renames T.E; You can even rename an array slice as an object: procedure P (S : String) is O : String renames S (1..4); Cool, huh? >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); Technically, the assignment operator ":=" isn't really an operator (I don't know the exact reasons, you'll have to ask the language theory gods...). You can't "add" an "assignment operator" to a type that is already declared as limited private, but you can get control of assignment if your type is (non-limited) private by deriving from type Finalization.Controlled: with Finalization; package Lists is type List is private; ... private type Node; type Node_Access is access Node; type List is new Finalization.Controlled with record Head : Node_Access; end record; end Lists; That way L1 := L2; can have value (copy) semantics rather than reference semantics. > >5- Do the ADA83 standard specify that the deallocation of memory is > automatically done? Or must I ensure that my program does it? You must make sure no memory leaks occur. There are pragmatic reasons for not mandating that Ada herself take care of the clean-up, specifically that the use of a garbage collector can cause unpredictable run-time behavior. But you don't have to worry about memory leaks if you inherit from Finalization.Controlled, which will invoke a subprogram to finalize the object (reclaim its storage, in this case) when its lifetime ends. > > 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)? If List is implemented as inheriting from Controlled, then all is well, and you (the client of L) don't have to free the memory yourself. > The next problem is that probably i would have allocated some extra > memory for the elements of L; will it be also freed automaticaly? > Some language do it (SML, SMALLTALK), some don't (MODULA-2, C, C++) > > However, we could define a destructor in C++; is it possible in ADA > that the destructor would be automatticaly called when the > object fall out of scope? The "deconstructor" is a primitive operation (called Finalize) of types that inherit from Controlled, that gets invoked automatically when the scope of an object closes. >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). Yes. It's called Text_IO.Get_Immediate. >I know that's a lot of questions to answer but that would be VERY >appreciated. > >Please reply by mail. Thank you. Your very welcome! Keep the posts a-comin'! >Benoit Rochefort >jk791840@er.uqam.ca Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant mheaney@ni.net (818) 985-1271