From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 20 Jan 93 23:56:37 GMT From: dale.cts.com!jhb@nosc.mil (John Bollenbacher) Subject: Isomorphic variant question Message-ID: List-Id: I often find myself with the following coding dilemma and would appreciate any insights. We build systems in which we use mail as our major inter-task communication mechanism. In general, the mail type takes the form of variant records. >>From time to time, we end up declaring such mail wherein more than one discriminant has the same variants associated with it. For example: type SHAPES is (CIRCLE, SQUARE, RECTANGLE); type SHAPE(KIND : SHAPES := SHAPES'FIRST) is record case KIND is when CIRCLE | SQUARE => CENTER : CORRDINATES; RADIUS : UNITS; when ... end case; end record; In the construction of a given piece of mail, we like to use aggregates to ensure that any changes in mail declarations will result in the compiler telling us what needs to change. So far so good. My recurring problem arises when I have a code fragment which is responsible for building such a piece of mail which does not need to distinguish between these isomorphich variants (CIRCLE and SQUARE in this case). Due to the fact that discriminants in aggregates which control the existence of variant fields must be static, I find myself unable to write straightforward code which reflects the fact that the fragment does not care about the specific value. The three approaches I have come up with (and their perceived shortcomings) are : 1. Duplicate the aggregates (Disadvantage: all of the disadvantages which accrue to duplicate code, in general): procedure POST(KIND : SHAPES) is begin case KIND is when CIRCLE => SEND((KIND => CIRCLE, CENTER => CENTER_OF_OBJECT, RADIUS => RADIUS_OF_OBJECT)); when SQUARE => SEND((KIND => SQUARE, CENTER => CENTER_OF_OBJECT, RADIUS => RADIUS_OF_OBJECT)); ... 2. Declare the object uninitialized and fill in the fields without an aggregate (Disadvantage: future modifications to the mail type will not be caught by the compiler): procedure POST(KIND : SHAPES) is MAIL : SHAPE(KIND); begin case KIND is when CIRCLE | SQUARE => MAIL.CENTER := CENTER_OF_OBJECT; MAIL.RADIUS := RADIUS_OF_OBJECT; SEND(MAIL); ... 3. Declare a 'temporary' repository with an arbitrary discriminant and initialize it with an aggregate. Then declare the real object and fill in the fields individually from the temporary object. (Disadvantage: extra copying required; a little unclear to future maintainers): procedure POST(KIND : SHAPE) is MAIL : SHAPE(KIND); begin case KIND is when CIRCLE | SQUARE => declare TMP : constant SHAPE := ( KIND => CIRCLE, CENTER => CENTER_OF_OBJECT, RADIUS => RADIUS_OF_OBJECT); begin MAIL.CENTER := TMP.CENTER; MAIL.RADIUS := TMP.RADIUS; ... Any comments or suggestions would be appreciated. -- ----------------------------------------------------------------------------- - John Bollenbacher jhb@dale.cts.com - - Titan Linkabit Corp. (619) 552-9963 - - 3033 Science Park Rd. - - San Diego, Ca. 92121 - -----------------------------------------------------------------------------