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_MSGID, PDS_OTHER_BAD_TLD autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,a415d3a613d86a4e X-Google-Attributes: gid103376,public From: mheaney@ni.net (Matthew Heaney) Subject: Making Predefined Operators Abstract Date: 1997/12/06 Message-ID: #1/1 X-Deja-AN: 295860259 References: <662cs9$b34$1@newman.pcisys.net> <3486C057.6207@gsfc.nasa.gov> <66c2rb$hdg$1@peuplier.wanadoo.fr> Organization: Estormza Software Newsgroups: comp.lang.ada Date: 1997-12-06T00:00:00+00:00 List-Id: In article <66c2rb$hdg$1@peuplier.wanadoo.fr>, "Jean-Pierre Rosen" wrote: >Robert Dewar said >>Matthew says >> >><you >>want anyway. What's wrong with a good old fashioned integer type? >>>> >> >>For one thing, it provides operations like addition, which are probably >>meaningless nonsense. >> >Sure, but don't forget that you can forbid direct calls by redefining the >functions as abstract. > >(Just taking the opportunity to remind people of that relatively unknown >feature) I like to do that so I don't use the predefined equality for arrays or records accidently, because the predefined equality of the component reemerges. For example, if I implemented a stack this way generic type Stack_Item is private; Max_Depth : Positive; package Stacks is type Bounded_Stack is tagged private; function "=" (L, R : Bounded_Stack) return Boolean; ... private subtype Top_Range is Natural range 0 .. Max_Depth; subtype Item_Array_Range is Top_Range range 1 .. Top_Range'Last; type Item_Array is array (Item_Array_Range) of Stack_Item; type Bounded_Stack is tagged record Items : Item_Array; Top : Top_Range := 0; end record; end Stacks; package body Stacks is function "=" (L, R : Bounded_Stack) return Boolean is begin return L.Items (1 .. L.Top) = R.Items (1..R.Top); end; ... end Bounded_Stacks; The problem with this implementation of equality is that it's probably wrong. The predefined equality operation for Stack_Item reemerged by not explicitly importing the equality operation as a formal operation. So I would do this: generic type Stack_Item is private; with function "=" (L, R : Stack_Item) return Boolean is <>; package Bounded_Stacks is ...; However, the equality operation for Stack that I defined above is still wrong! The problem now is that predefined equality reemerged as a result of making Stack_Item an array component Array comparisons use the predefined equality of the component, in spite of the fact that equality was imported as a formal operation. The solution is to not use array comparison at all to implement stack comparision: function "=" (L, R : Bounded_Stack) return Boolean is begin if L.Top /= R.Top then return False; end if; for Index in Item_Array_Range range 1 .. L.Top loop if L.Items (Index) /= R.Items (Index) then return False; end if; end loop; return True; end "="; All of this was leading up to making a predefined operation abstract. Because we definately do not want to use array comparison, we take it away as follows: private ... type Item_Array is array (Item_Array_Range) of Stack_Item; function "=" (L, R : Item_Array) return Boolean is abstract; -- Note this line type Bounded_Stack is ...; Now neither you nor a naive maintenance programmer can accidently use array equality, because that operation is abstract. A guideline for writers of data structures is to always import equality (to give the client the opportunity to use his own definition) and to not use predefined array equality for an array having the imported type as a component. You must invoke the imported equality of the component type directly. Declaring the array equality as abstract enforces this. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant (818) 985-1271