Version 1.1 of acs/ac-00327.txt

Unformatted version of acs/ac-00327.txt version 1.1
Other versions for file acs/ac-00327.txt

!standard 3.2.4(15/3)          20-03-09 AC95-00327/00
!standard 5.4(7/4)
!standard 13.9.2(3/4)
!class confirmation 20-03-09
!status received no action 20-03-09
!status received 20-03-05
!subject Non-contiguous range of enumeration types
!summary
!appendix

!topic not contiguous range subtype of enumerated type
!reference Ada 2012 3.5.1(42)
!from M. Guerra 20-03-05
!keywords enumerated subtype
!discussion:

Please, be so kind as to consider:

type Rainbow_Color is (Red, Orange... Violet);

would it be extremely complex for compiler vendors or inconvenient for the
language semantics to include the possibility of non-contiguous range enumerated
subtypes? Like the following:

subtype Traffic_Light_Color is subset(Red .. Orange, Green) of Rainbow_Color;

The road to set arithmetic would then be open for enumerated types:

subtype Non_Traffic_Light_Color is Rainbow_Color - Traffic_Light_Color;

***************************************************************

topic subtype-based Valid attribute
!reference Ada 2012 13.9.2(324)
!from M: Guerra 20-03-05
!keywords Valid attribute for enumerated subtypes

!discussion:

Please, be so kind as to consider:

type Rainbow_Color is (Red, Orange... Violet);

subtype Traffic_Light_Color is subset(Red .. Orange, Green)
   of Rainbow_Color; -- illegal, up to now

would it be extremely complex for compiler vendors or inconvenient for the
language semantics to include the possibility of the Valid attribute being based
on a subtype when appropriate? Like the following:

Input_Color : Rainbow_Color;

if Traffic_Light_Color'Valid(Input_Color) then
   when Red    => Remain_Stopped;
   when Orange => Break_Until_Stopped;
   when Green  => Go;
end if; -- the need for error-prone when others disappears.

This proposal would make sense, imho, for any enumerated subtype, whether it is
a contiguous range of the base enumerated type or not.

***************************************************************

From: Christoph Grein
Sent: Thursday, March 5, 2020  4:47 AM

subtype TLC is RC with Dynamic_Predicate => TLC in Red .. Orange | Green;

subtype NTLC is RC with Dynamic_Predicate => NTLC not in TLC;

***************************************************************

From: Tucker Taft
Sent: Thursday, March 5, 2020  4:58 AM

Actually, you can use a Static_Predicate for this, and then you can use the
subtype in things like case choices and loop ranges, and in defining
Static_Predicates.

  subtype TLC is RC with Static_Predicate => TLC in Red .. Orange | Green;

  subtype NTLC is RC with Static_Predicate => NTLC not in TLC;

***************************************************************

From: Randy Brukardt
Sent: Thursday, March 5, 2020  7:37 PM

...
>would it be extremely complex for compiler vendors or inconvenient for
>the language semantics to include the possibility of the Valid
>attribute being based on a subtype when appropriate? Like the
>following:

The Valid attribute has always been "based on a subtype"; the range of the
subtype is always part of the result (for any type that Valid is allowed for).
With Ada 2012, predicates are included as well. But Valid is always applied to
objects; it is the subtype of the object that is used for this check. There are
important semantic reasons why the object has to be the prefix of 'Valid; if it
was the argument, then the object would need to be read first and that would
necessarily trigger the possibility of raising Program_Error for using an
invalid object.

Note that the same is true for membership operations, so your example can be
written as follows (assuming that the object cannot be declared with the subtype
for some reason (note that you left out part of the case statement as well - you
have a bizarre mixture of a if and a case):

type Rainbow_Color is (Red, Orange... Violet);

subtype Traffic_Light_Color is Rainbow_Color
   with Static_Predicate => Traffic_Light_Color in Red .. Orange | Green;

Input_Color : Rainbow_Color;

if Input_Color'Valid and then Input_Color in Traffic_Light_Color then
   case Traffic_Light_Color(Input_Color) is
      when Red    => Remain_Stopped;
      when Orange => Break_Until_Stopped;
      when Green  => Go;
   end case; -- No Others needed here.
else
   raise Invalid;
end if;

Of course, if you don't mind raising Constraint_Error, you can just use the case
statement.

***************************************************************

From: Randy Brukardt
Sent: Thursday, March 5, 2020  8:02 PM

>Please, be so kind as to consider:
>
>type Rainbow_Color is (Red, Orange... Violet);
>
...
>subtype Traffic_Light_Color is subset(Red .. Orange, Green) of
Rainbow_Color;

We did, it was AI05-0153-2 (the last version can be read at
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0153-2.txt?rev=1.9&raw=Y)

The proposed syntax was "when":

subtype Traffic_Light_Color is Rainbow_Color when Red .. Orange | Green;

This proposal was scrapped in favor of Static_Predicates, which have similar
semantics but are a lot wordier:

subtype Traffic_Light_Color is Rainbow_Color with
     Static_Predicate => Traffic_Light_Color in Red .. Orange | Green;

I still think the other proposal was a better idea, but I think I was literally
the only one that felt that.

As Tucker noted, this type can be used in case statements and for loops with
the expected semantics (in particular, no others clause is needed in a case).
See my other reply for an example.

>The road to set arithmetic would then be open for enumerated types:

Here I need to make the normal general reminder. We *always* want to have use
cases provided along with any proposed features. It's easy to dream up possible
features, but we're not likely to add new features to the language unless they
meet a demonstratable need that is impractical or overly complex today. Each new
feature has a cost to the complexity of the Standard, the complexity of learning
and using the language, and to the effort to implement the language.

It also helps to be able to determine if there is a way to handle the need with
existing features (since it is not usual for posters here to not know about some
existing Ada capability that provides part or all of what they want).

In this particular case, I don't think that "set arithmetic" would be used very
often for subtypes. (I can't think of any cases where I would have wanted such a
thing.) This wouldn't be the same as doing runtime set arithmetic (which is
provided somewhat less conveniently by both Ada.Containers.Ordered_Sets and by
the built-in operations on packed arrays of Boolean). I would need to see some
use cases to convince me otherwise.

***************************************************************

From: Mario Daniel Guerra Garcia
Sent: Monday, March 9, 2020  5:30 AM

   Thank you!!!!

I'm afraid I'm not "fluent" enough with predicates as to have realized on my own
and I have missed the non-contiguous subtype feature more than once.

   Being part of a maintenance team, we work on legacy code with legacy
   compilers and Ada2012 is not an option, as yet.

   I'm sorry to have troubled you.

***************************************************************

Questions? Ask the ACAA Technical Agent