comp.lang.ada
 help / color / mirror / Atom feed
* others clause
@ 1996-08-29  0:00 Chris Sparks
  1996-08-30  0:00 ` Mike Bishop
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Chris Sparks @ 1996-08-29  0:00 UTC (permalink / raw)



Why is the following not incorrect?

---------------------------------------------------------------------
procedure T is

  type Enum is (A, B, C, D, E, F);

  T1 : Enum    := Enum'First;
  T2 : Integer := 0;

begin
  case T1 is
    when A      => null;
    when B      => null;
    when C      => null;
    when D      => null;
    when E      => null;
    when F      => null;
    when others => null;               --WHY ISN'T THIS ERRONEOUS?
  end case;

  case T2 is
    when Integer'First .. -1 => null;
    when 0                   => null;
    when 1 .. Integer'Last   => null;
    when others              => null;  --WHY ISN'T THIS ERRONEOUS?
  end case;

end T;
---------------------------------------------------------------------
It seems to me that if we have identified all of the possible values,
then other would be invalid.  You can't test for others in the above
two cases!

Any feedback would be appreciated.

Chris Sparks (aka Mr. Ada)
sparks@aisf.com




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-29  0:00 others clause Chris Sparks
@ 1996-08-30  0:00 ` Mike Bishop
  1996-08-31  0:00   ` Robert A Duff
                     ` (3 more replies)
  1996-08-31  0:00 ` Robert Dewar
  1996-09-02  0:00 ` Stephen Bull
  2 siblings, 4 replies; 9+ messages in thread
From: Mike Bishop @ 1996-08-30  0:00 UTC (permalink / raw)



Chris Sparks wrote:
> 
> Why is the following not incorrect?
> 
> ---------------------------------------------------------------------
> procedure T is
> 
>   type Enum is (A, B, C, D, E, F);
> 
>   T1 : Enum    := Enum'First;
>   T2 : Integer := 0;
> 
> begin
>   case T1 is
>     when A      => null;
>     when B      => null;
>     when C      => null;
>     when D      => null;
>     when E      => null;
>     when F      => null;
>     when others => null;               --WHY ISN'T THIS ERRONEOUS?
>   end case;

According to the Ada 95 LRM, section 5.4, each value of T1 must be
covered either explicitly by a non-other discrete choice or by others.
That is the case in the above code. The LRM does not state that if all
values are covered by non-other choices, then others is not allowed. In
fact, using others is a good idea even when all values are explicitly
covered. If you add more values to the type but forget to modify the
case statement, you can still handle the new values in the others
choice.

>   case T2 is
>     when Integer'First .. -1 => null;
>     when 0                   => null;
>     when 1 .. Integer'Last   => null;
>     when others              => null;  --WHY ISN'T THIS ERRONEOUS?
>   end case;
> 
> end T;

Not only is others not erroneous here, it is required. If the type of
the case expression is root_integer or universal_integer, you must have
an others choice.

-- 
Mike Bishop         
mbishop@ghgcorp.com 
http://www.ghgcorp.com/mbishop/




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-30  0:00 ` Mike Bishop
@ 1996-08-31  0:00   ` Robert A Duff
  1996-09-02  0:00   ` Brian Rogoff
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Robert A Duff @ 1996-08-31  0:00 UTC (permalink / raw)



In article <3227AAA6.67C9@ghgcorp.com>,
Mike Bishop  <mbishop@ghgcorp.com> wrote:
>Chris Sparks wrote:
>>     when others => null;               --WHY ISN'T THIS ERRONEOUS?

I think Chris means "illegal", not "erroneous".  Ada doesn't use
"erroneous" in its normal English sense.

>fact, using others is a good idea even when all values are explicitly
>covered. If you add more values to the type but forget to modify the
>case statement, you can still handle the new values in the others
>choice.

Yeah, at least in *some* cases, you want to have the empty others case,
in case you add new values later.  In other cases, though, you *want* to
get a compile-time error, so you can analyze the newly added cases -- in
those cases, don't put "others".

Another reason for allowing seemingly-empty others clauses is to handle
out-of-range values.  Consider, for example:

   T2: Integer := Integer'Last;

   case T2 + 1 is
     when Integer'First .. -1 => null;
     when 0                   => null;
     when 1 .. Integer'Last   => null;
     when others              => null;
   end case;

T2+1 might overflow, raising Constraint_Error.  Or, it might produce a
value outside the range of Integer, and thus jump to the others case.
Similarly, the variable being testing might have an uninitialized value
outside the range of the type (although that's unlikely for Integer).
Note that these cases are not erroneous -- we have tried to minimize the
possibility of wild jumps in Ada 95.  Here's a slightly more realistic
example:

    type My_Int is range -2**15..2**15-1;
    
    X, Y: My_Int := ...;
    
    case X+Y is
       when -2**15..-1 => ...;
       when 0..2**15-1 => ...;
       when others => ...;
    end case;

In this case, 5.4(9) requires each value in My_Int'Base to be covered.
But that range is implementation defined!  We don't want the legality of
that "others" to depend on whether the compiler happened to choose a
16-bit or 32-bit machine type to represent My_Int'Base.

>Not only is others not erroneous here, it is required. If the type of
>the case expression is root_integer or universal_integer, you must have
>an others choice.

No, the case expression was of type Integer, not root_integer or
universal_integer -- no others required.

- Bob




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-29  0:00 others clause Chris Sparks
  1996-08-30  0:00 ` Mike Bishop
@ 1996-08-31  0:00 ` Robert Dewar
  1996-09-02  0:00 ` Stephen Bull
  2 siblings, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1996-08-31  0:00 UTC (permalink / raw)



iChris asks

  case T1 is
    when A      => null;
    when B      => null;
    when C      => null;
    when D      => null;
    when E      => null;
    when F      => null;
    when others => null;               --WHY ISN'T THIS ERRONEOUS?
  end case;

first of all you do not mean erroneous, please be careful with this
terminology. Erroneous is a technical term in Ada with very specific
meaning and it is confusing to use it in its non-tecynical sense.
You mean illegal, another technical term, which should also be used
only for its exact purpose.l

This certainly is not illegal according to the definition in the RM,
which I assume is clear (if you are asking about how to read this
in the RM, then reask, it's straightforward).

SO I assume this is a "why is Ada designed this way" type question?

In fact I think it is highly desirable to allow a redundant others
branch. Basically the others says, do this if I have not specifically
taken care of it otherwise.

In some cases, it may not be at all clear whether you have taken care
of all branches, or may depend on constants that are configurable, and
you do not want changing the configurable constant to mean that you have
to go around chnaging case statements around the place.

I think a compiler warning is *possibly* advisable/acceptable, but I
would need to think more about this.

Incidentally, in GNAT, a common usage is

	when others =>
	   pragma Assert (False); null;

to generally note that you did not expect to get into the other section,
either because all cases were covered, or because the logic says you should
not be here.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-30  0:00 ` Mike Bishop
  1996-08-31  0:00   ` Robert A Duff
  1996-09-02  0:00   ` Brian Rogoff
@ 1996-09-02  0:00   ` Geert Bosch
  1996-09-03  0:00     ` Robert Dewar
  1996-09-03  0:00   ` Adam Beneschan
  3 siblings, 1 reply; 9+ messages in thread
From: Geert Bosch @ 1996-09-02  0:00 UTC (permalink / raw)



Mike Bishop (mbishop@ghgcorp.com) wrote:
`` In fact, using others is a good idea even when all values are
   explicitly covered. If you add more values to the type but forget to
   modify the case statement, you can still handle the new values in
   the others choice. ''

I disagree on this. Say you have code to handle situations A, B and C and
these situations are the only ones known to you. Then it is a bad practise
to use an "others" choice, because you don't know what would be a good
reaction for others.

It is better to use no others clause. When you add some new situation D
to your program and didn't think about effects on the rest of the code, 
the compiler will show the place where you have to decide what to do about
case 'D'. Then you can think whether a "null" statement would be the
right solution, or whether you should really raise an exception if 
situation D is ever encountered at that place.

Forgetting to check if assumptions are still valid when circumstances
change is a very common and potentially disastrous error (think of the
Ariane 5). Using language features to check as much of your reasoning 
as possible is a good thing IMHO. 

Actually, one of the big dangers of object-oriented programming is
that assumptions that hold for a base class do not necessarily
hold for derived classes. Too many people think that OOP easily
scales to large projects and that code reuse is safe, without
even thinking about the possible problems.

One of the features I'm really missing in Ada is a syntax to
specify assertions, pre- and post-conditions and invariants for
code and interfaces. Compilers wouldn't have to check these
conditions, except some simple cases like static expressions,
but they (or external programs) *could* check them and moreover
compilers could use them for optimizations.

Any new revision of Ada should address this issue, since it
is so closely connected to the design goals of Ada.
-- 
E-Mail: geert@sun3.iaf.nl    
      ``I think there is a world market for maybe five computers.''
        Thomas Watson,  chairman of IBM, 1943





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-29  0:00 others clause Chris Sparks
  1996-08-30  0:00 ` Mike Bishop
  1996-08-31  0:00 ` Robert Dewar
@ 1996-09-02  0:00 ` Stephen Bull
  2 siblings, 0 replies; 9+ messages in thread
From: Stephen Bull @ 1996-09-02  0:00 UTC (permalink / raw)




In article <50d4fc$elf@fozzie.sun3.iaf.nl> geert@fozzie.sun3.iaf.nl
(Geert Bosch) writes:

>   One of the features I'm really missing in Ada is a syntax to
>   specify assertions, pre- and post-conditions and invariants for
>   code and interfaces. Compilers wouldn't have to check these
>   conditions, except some simple cases like static expressions,
>   but they (or external programs) *could* check them and moreover
>   compilers could use them for optimizations.

The SPARK language is a secure subset of Ada augmented by an set of annotations
which allow such checks to be made by the support tool the SPARK Examiner.
SPARK is developed and supported by Praxis Critical Systems.
For more information please refer to our web pages:

http://www.praxis.co.uk/technols/spark/sp_lang.htm

-- 
-----------------------------------------------------------------------------
 Stephen Bull  Praxis Critical Systems  20 Manvers Street  BATH  BA1 1PX  UK
    +1225 444700 (switchboard)  +1225 739286 (direct)  +1225 739281 (fax)
-----------------------------------------------------------------------------
-- 
-----------------------------------------------------------------------------
 Stephen Bull  Praxis Critical Systems  20 Manvers Street  BATH  BA1 1PX  UK
    +1225 444700 (switchboard)  +1225 739286 (direct)  +1225 739281 (fax)
-----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-30  0:00 ` Mike Bishop
  1996-08-31  0:00   ` Robert A Duff
@ 1996-09-02  0:00   ` Brian Rogoff
  1996-09-02  0:00   ` Geert Bosch
  1996-09-03  0:00   ` Adam Beneschan
  3 siblings, 0 replies; 9+ messages in thread
From: Brian Rogoff @ 1996-09-02  0:00 UTC (permalink / raw)



geert@fozzie.sun3.iaf.nl (Geert Bosch) writes:
   Actually, one of the big dangers of object-oriented programming is
   that assumptions that hold for a base class do not necessarily
   hold for derived classes. Too many people think that OOP easily
   scales to large projects and that code reuse is safe, without
   even thinking about the possible problems.

Right. I think it is a problem that there are assumptions about 
signature, behavior, specification (pre/post condition), and protocols 
that have to be dealt with that are now mostly dealt with by comments. 
It would be great if something better than systematic commenting was 
available but I am not sure if it belongs in the core language, which 
is already a bit large.

   One of the features I'm really missing in Ada is a syntax to
   specify assertions, pre- and post-conditions and invariants for
   code and interfaces. Compilers wouldn't have to check these
   conditions, except some simple cases like static expressions,
   but they (or external programs) *could* check them and moreover
   compilers could use them for optimizations.

Do you think that this needs to be part of the language proper, or would 
add-on tools suffice? Wasn't Anna supposed to do fill this goal? Larch?
Standardizing an existing tool might be a reasonable interim solution. 

   Any new revision of Ada should address this issue, since it
   is so closely connected to the design goals of Ada.

Indeed.

-- Brian






^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-08-30  0:00 ` Mike Bishop
                     ` (2 preceding siblings ...)
  1996-09-02  0:00   ` Geert Bosch
@ 1996-09-03  0:00   ` Adam Beneschan
  3 siblings, 0 replies; 9+ messages in thread
From: Adam Beneschan @ 1996-09-03  0:00 UTC (permalink / raw)



In article <3227AAA6.67C9@ghgcorp.com> mbishop@ghgcorp.com writes:
 >Chris Sparks wrote:
 >> 
 >> Why is the following not incorrect?
 >> 
 >> ---------------------------------------------------------------------
 >> procedure T is
 >> 
 >>   type Enum is (A, B, C, D, E, F);
 >> 
 >>   T1 : Enum    := Enum'First;
 >>   T2 : Integer := 0;
 >> 
 >> begin
 >>   case T1 is
 >>     when A      => null;
 >>     when B      => null;
 >>     when C      => null;
 >>     when D      => null;
 >>     when E      => null;
 >>     when F      => null;
 >>     when others => null;               --WHY ISN'T THIS ERRONEOUS?
 >>   end case;
 >
 >According to the Ada 95 LRM, section 5.4, each value of T1 must be
 >covered either explicitly by a non-other discrete choice or by others.
 >That is the case in the above code. The LRM does not state that if all
 >values are covered by non-other choices, then others is not allowed. In
 >fact, using others is a good idea even when all values are explicitly
 >covered. If you add more values to the type but forget to modify the
 >case statement, you can still handle the new values in the others
 >choice.

Actually, this may be a good time to throw in one of my pet theories,
developed from bitter experience: that you should NEVER (or almost
never) use "when others" on an enumeration type.  (I believe that
others have come to the same conclusion as I have.)

The reason is: "When Others" applies not only to the enumeration
values that have been defined for the type but not listed elsewhere in
the CASE; it also applies to all other enumeration values that you
could conceivably add to the enumeration type in the future.  So, if
you have a really good crystal ball and you know that you will never
be adding more values to the enumeration type, or that the code you
write for "when others" will apply to all values that you will add in
the future, it's OK to use "when others".  Otherwise, don't.  

If you do, what will happen (this has happened to me a number of
times) is that you will decide you need to extend the enumeration type
with new values, and you'll look through the program to find all the
cases where a value of the enumeration type is used in a CASE
statement, or in a CASE clause in a record definition, to see if the
code needs to be modified.  But you'll miss one or two instances, and
the program will compile with no problem, and it will turn out that
the code in the "when others" clause was inappropriate to the new
enumeration value.  Now your program has a bug that you'll have to
track down, assuming it's caught before you release it to the
customer. 

On the other hand, if you avoid "when others", you'll still look
through the program to find all the places where the enumeration type
is used in a CASE statement, and you'll still miss one or two.  But
this time, the compiler won't compile the cases you've missed, since
the language requires that all values of the enumeration must covered
by the CASE choices.  This makes it harder to create a program bug
accidentally.

                                -- Adam





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: others clause
  1996-09-02  0:00   ` Geert Bosch
@ 1996-09-03  0:00     ` Robert Dewar
  0 siblings, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1996-09-03  0:00 UTC (permalink / raw)



"Mike Bishop (mbishop@ghgcorp.com) wrote:
`` In fact, using others is a good idea even when all values are
   explicitly covered. If you add more values to the type but forget to
   modify the case statement, you can still handle the new values in
   the others choice. ''"

This seems a terrible idea to me. One of the great advantages of the
case statement in Ada is precisely the check that you have explicitly
covered every alternative.

I prefer to avoid others choices whereever possible, and instead write
out the list of alternatives that corresponds to what naturally might
otherwise be written as others. Then each time you add a case, your
compiler forces you to visit each case statement and think about whether
or not it belongs in the "others" branch.





^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~1996-09-03  0:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-08-29  0:00 others clause Chris Sparks
1996-08-30  0:00 ` Mike Bishop
1996-08-31  0:00   ` Robert A Duff
1996-09-02  0:00   ` Brian Rogoff
1996-09-02  0:00   ` Geert Bosch
1996-09-03  0:00     ` Robert Dewar
1996-09-03  0:00   ` Adam Beneschan
1996-08-31  0:00 ` Robert Dewar
1996-09-02  0:00 ` Stephen Bull

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox