shouting versus dotting

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun Oct 5 17:03:08 PDT 2008


Jason House wrote:
> Andrei Alexandrescu wrote:
> 
>> Leandro Lucarella wrote:
>>> "enum" as the way to declare manifest constants were much more ugly than
>>> "!(", and most of the people were against it. I don't see why ".(" should
>>> be introduced.
>> Ugly or not, enumerated symbols were manifest constants to begin with.
>> That's kinda hard to argue against because it's a sheer fact.
> 
> Even before we expanded enums, I hated how there was no toString() for enum
> types.

defineEnum in std.typecons provides that (and parsing too).

> Walter explained this was because bit masks made it difficult. I
> like using enums for a restricted set of options.  That'd allow the
> compiler to provide toString and catch misuse in switch statements...
> Including when I add or remove allowed values.

Walter hasn't gotten around to implementing the final switch statement, 
which does exactly as you mention. For the interested I paste the 
relevant section in TDPL - hot off the oven:

\section{The \protect\cc{final switch} Statement}

It is  often the case  that @switch@ is  meant to handle  all possible
cases,  such as  all values  of a  small integer  or of  an enumerated
type. If, during maintenance, the  number of cases is changing, all of
the dependent @switch@  statements suddenly fall out of  sync and must
be  manually searched  for  and modified.   For  such situations,  the
\cc{final switch} statement comes in handy:

\begin{D}
enum deviceStatusMask = 3;
...
void Handle(uint x) {
   final switch (x & deviceStatusMask) {
   case 0: ...
   case 1: ...
   case 2: ...
   case 3: ...
   }
}
\end{D}

Should  the value of  @mask@ change  later to,  say, 7,  attempting to
recompile @Handle@ is met with refusal on the following grounds:

\begin{lstlisting}[language=sys]
Error: final switch statement must handle all values
\end{lstlisting}

The \cc{final switch} statement looks  at the shape of its controlling
expression to figure out the bounds, as follows:

\begin{itemize*}
\item  If \meta{expression}  is \metai{e}  @&@ \metaii{e}  and  one of
   \metai{e} and \metaii{e} evaluates  to a positive compile-time value
   @c@, then the range is determined as @0@ up to (and including) @c at .
\item  If  \meta{expression}   is  \metai{e}  \cc{\%}  \metaii{e}  and
   \metaii{e} evaluates to a  positive compile-time value @c@, then the
   range is determined as @0@ up to (and not including) \cc{c}.
\item  If  \meta{expression}  is   an  unsigned  right  shift  (either
   \metai{e}  \cc{>>}  \metaii{e}  operating  on unsigned  numbers,  or
   \metai{e}  \cc{>>>} \metaii{e}),  and if  \metaii{e} evaluates  to a
   compile-time value  @c@, then the range  is determined as  @0@ up to
   (and not including) \cc{1 << (8 *} \metai{e}\cc{.sizeof - c)}.%>>
\item If  \meta{expression} is  the assignment variant  of one  of the
   above  (@&=@, \cc{\%=}  etc.) then  the range  the same  as  for the
   non-assignment variant.
\item If  \meta{expression} is  an enumerated type,  the range  is the
   entire set of values of the enumerated type.
\item   Otherwise,  the  range   is  @e.min@   up  to   and  including
   @e.max at . (The @min@ and @max@  constants are defined for all numeric
   types.)
\end{itemize*}

There are quite a few other  cases in which the range of an expression
could be  effectively determined,  but \cc{final switch}  only handles
the  usual ones.   A @default@  label  is allowed  inside a  \cc{final
   switch} statement  and practically turns  off all checks  because it
ensures \emph{de facto} that all values are handled.


Andrei



More information about the Digitalmars-d mailing list