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.4 required=5.0 tests=BAYES_00,FORGED_MUA_MOZILLA autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,81bb2ce65a3240c3 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.68.125.201 with SMTP id ms9mr3515900pbb.3.1336330081654; Sun, 06 May 2012 11:48:01 -0700 (PDT) Path: pr3ni11549pbb.0!nntp.google.com!news1.google.com!news4.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: What would you like in Ada202X? Date: Sun, 06 May 2012 21:48:00 +0300 Organization: Tidorum Ltd Message-ID: References: <3637793.35.1335340026327.JavaMail.geo-discussion-forums@ynfi5> Mime-Version: 1.0 X-Trace: individual.net TWKeym6f+bDNf8KAKImTBgRinpteKc0VshpdhAbhDGATORMOpQM9JCDiYz89NIlsFV Cancel-Lock: sha1:YvSRjfuypqkCiI5dPChMgi31c9A= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 In-Reply-To: <3637793.35.1335340026327.JavaMail.geo-discussion-forums@ynfi5> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Date: 2012-05-06T21:48:00+03:00 List-Id: On 12-04-25 10:47 , Martin wrote: > Ok, we don't officially have Ada2012 yet but as no new features are > going to be added to it, now seems like a good time to start thinking > about the next revision. There is a proposal for extensible enumerated types, AI95-261 (http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-00261.txt), that was rejected (and I don't much like it, either). While reading John Barnes' second part of "Rationale for Ada 2012" in Ada User Journal, for some reason an idea came to me of a different and perhaps better concept of extension for enumerated types. I'm not sure that this would be a worth-while addition to Ada, but here it is, for your pleasure or displeasure, as briefly as I could write it. The new concept can be describes as "extending enumerated types by deepening", where the AI95-261 concept is "extending by widening". The terms "deepening" and "widening" come from seeing an enumerated type as a classification of some set of things. For example, the messages exhanged in some protocol could be classified in this way, initially and roughly: type Message_Kind1 is (Sign_On, Request, Reply, Sign_Off); and some general operations might be written using only this rough classification. AI95-261 proposed the ability to derive a "wider" type with more literals, as in: type Wider_Message_Kind1 is new Message_Kind1 with (Tick, Ping); The main problem with this extension by widening is that the derived type, Wider_Message_Kind1, is not a "subclass" of the parent type, because some values of the derived type (the new literals) cannot be converted to (or viewed as) values of the parent type. The derived type can't inherit operations from the parent type, because those operations can't handle the added values. AI95-261 suggests to raise Constraint_Error in such cases. Note how this differs from derived tagged types. In "extension by deepening", the classification is not widened by adding more literals "at the end", but is deepened, or refined, by dividing some or all of the parent literals into a set of new literals, to give a more detailed classification. In the protocol example, we can distinguish different kinds of Request: a read request or a write request, and different kinds of Reply: some data (in reply to a read request), an ack (in reply to a write request), or a refusal (in reply to any invalid request). The derivation syntax could be like this: type Detailed_Message_Kind is new Message_Kind1 with ( Request => (Read, Write), Reply => (Data, Ack, Refused), others => <>); The part "others => <>" is an abbreviation for "Sign_On => (Sign_On), Sign_Off => (Sign_Off)" and means that the literals Sign_On and Sign_Off are not refined in this derivation. The derived enumerated type Detailed_Message_Kind has the following properties: - Its literals are, in order: Sign_On, Read, Write, Data, Ack, Refused, Sign_Off. Note that the Message_Kind1 literals Request and Reply are not included, because they are refined into several new literals. - It inherits all primitive operations of Message_Kind1, except those with "out" or "in out" parameters of type Message_Kind1, and except functions that return Message_Kind1. (See below for alternative rules.) - Its values can be converted to type Message_Kind1 (including implicit conversion as an "in" parameter to an inherited operation) as follows: Sign_On to Sign_On Read to Request Write to Request Data to Reply Ack to Reply Refused to Reply Sign_Off to Sign_Off - At least conceptually, a Detailed_Message_Kind value is represented by some "parent" bits that represent a Message_Kind1 value (default encodings 0 .. 3), plus some "extension" bits that are different for Read and Write (0 and 1), and different for Data, Ack, and Refused (0, 1, and 2). For the Message_Kind1 literals that are not refined (Sign_On and Sign_Off) the extension bits are logically irrelevant but in practice would have a fixed value (zero seems natural). - Conversion from Detailed_Message_Kind to Message_Kind1 keeps the parent bits and discards the extension bits. - Conversion from Message_Kind1 to Detailed_Message_Kind is not allowed, because where would we get the values for the extension bits? This is why Detailed_Message_Kind does not inherit Message_Kind1 operations that produce values of type Message_Kind1. (An alternative design could define default values for the extension bits, for example that a Request is by default converted to a Read, but this seems a bit arbitrary. A further alternative is to allow conversion for literals that are not refined -- in the example, Sign_On and Sign_Off -- and raise Constraint_Error otherwise.) This kind of enumeration extension has some nice features: - It provides a way to describe hierarchical classifications in a value-based way, without involving references to tagged objects in a class hierarchy. - The values that describe the classification are discrete scalars, which can be used as discriminants and to index arrays and case statements. - The derived type inherits many operations of the parent type, and the derived type can substitute for the parent type (LSP). Extension by deepening can also implement a form of "extension by widening", as follows: The parent type is provided with an extra literal to provide the "root" of any new literals to be added in derived types. For example, here we use the literal "More" for this: type Message_Kind2 is (Sign_On, Request, Reply, Sign_Off, More); To "widen" the type by adding message-kinds Tick and Ping, the More literal is refined: type Wider_Message_Kind is new Message_Kind2 with ( More => (Tick, Ping, More), others => <>); Note that we added also a new literal More, so that Wider_Message_Kind can be widened further. Wider_Message_Kind has the literals Sign_On, Request, Reply, Sign_Off, Tick, Ping, More. A conversion from Wider_Message_Kind to Message_Kind2 maps the literals Tick, Ping, and (the new) More to Message_Kind2'(More). Thus, the new literals are all seen as Message_Kind2'(More) within the operations that Wider_Message_Kind inherits from Message_Kind2. As an option, some standard word or symbol could be standardized to serve the role of our "More" literal, above. For example, the reserved word "new" could be used for this. We could then come all the way back to AI95-261 as follows: if the parent type does not list "new" as a literal, but a derived type is derived by refining "new", then conversion from the derived type to the parent type is allowed only for the non-refined literals and raises Constraint_Error for the added literals. For example: type Wider_Message_Kind2 is new Message_Kind1 with new => (Tick, Ping, new); (Here I have used an abbreviated syntax, unambiguous in this case, without the outermost parentheses and with an assumed "others => <>".) Continuing to the next derivation level: type Widest_Message_Kind is new Wider_Message_Kind2 with new => (Greeting, Abort_Last_Request); Now: - Any value of Widest_Message_Kind can be converted to Wider_Message_Kind2. The literals Greeting and Abort_Last_Request are converted to Wider_Message_Kind2'(new). - An attempt to convert the Wider_Message_Kind2 values Tick, Ping, or Wider_Message_Kind2'(new) to Message_Kind1 raises Constraint_Error (because Message_Kind1 does not list the "new" literal). So, there it is. There is much that I haven't thought out, for example how representation clauses would work. But the main question is: would this feature be useful? Would it be too redundant with tagged types? What do you think? -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .