[comp.lang.c] problems/risks due to programming language

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/22/90)

From hammondr@sunroof.crd.ge.com (Richard A Hammond):
>>     3. The AT&T breakdown a month ago was caused by a break statement
>>	in C. See the following mail (multiple forwarding headers deleted):
> 
>>| | In the switching software (written in C), there was a long
>>| | "do . . . while" construct, which contained
>>| |    a "switch" statement, which contained 
>>| |       an "if" clause, which contained a
>>| |          "break," which was intended for
>>| |       the "if" clause, but instead broke from
>>| |    the "switch" statement.
>>| | 
>>
>>	Again it looks like this bug wouldn't have occurred in another
>>	programming language.
% 
% What other programming language?  Only one without any GOTO or restricted
% GOTO (e.g. exit, break, ...).  This leaves out Ada!!!!!!
% 
%  [...]  for N in 1 .. MAX loop 
% 	    case ...
% 	    when ... =>
%                 if NEW_ITEMS(N) = FALSE then 
% 			-- some other useful work gets done here
%                         exit; 			-- exits loop, not if!
%                 end if; 
% 	    when ... =>
%   [...] 
% So, in the AT&T case using Ada we would have exited both the switch and the
% loop rather than just the switch.  Hardly an improvement!

   This is not a valid analogy.  In C, the case statement *requires* the
   use of a restricted GOTO in order to accomplish "normal" processing;
   at the end of the section of code processing a given case, one must
   use a restricted GOTO in order to prevent C from sending the flow of
   control straight into the section of code which was intended to process
   the NEXT case.  In other words, C requires the programmer to use a
   dangerous construct on a routine basis.

   With the if construct in C, the default is to exit the if construct 
   automatically, as opposed to continuing on to execute the section of
   code associated with the else part.  Thus, we have an inconsistency
   in C's design: with one flow-of-control construct (the switch), it is
   necessary to use a dangerous GOTO to achieve normal processing, whereas
   with a similar flow-of-control construct (the if-else), the default is
   reversed.  Given such a language design, it should not surprise anyone
   that programmers become confused, particularly when the constructs are
   being used together. 

   Ada, on the other hand, is consistent: in both the if and case statements,
   the default is to exit the construct once the code associated with the
   specified situation has been executed.  Ada also provides the exit
   statement, a restricted GOTO which permits a loop to be exited early,
   but this construct is not used (as is C's break) on a routine basis.  

> In my limited experience the cases where Ada is introduced into a
> programming environment also introduce lots of other good software
> engineering practices.  For example, lots of people I know who
> program in C don't use LINT.   I view it as a deficiency of management
> and not of the language that they don't use available tools.

   This is certainly true; Brooks and others have noted that the good
   software engineering practices which are routinely introduced in
   conjunction with the Ada language are responsible for more of the 
   resulting improvements than the fact that the Ada language was
   introduced.  However, we cannot disregard that fact that Ada was
   specifically designed to provide maximal support for the software 
   engineering process.  C, on the other hand, was designed to provide
   maximal support for the compilation process.  Since compilers and 
   the CPU power required to operate them come far more cheaply than 
   programmers, and especially in view of the fact that better error
   prevention is worth much more than faster compilation, it would seem
   that the tradeoff made by Ada is certainly the one to be preferred.


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

jnixon@andrew.ATL.GE.COM (John F Nixon) (02/22/90)

billwolf (William Thomas Wolfe, 2847 ) writes:
>From hammondr@sunroof.crd.ge.com (Richard A Hammond):
>> So, in the AT&T case using Ada we would have exited both the switch and the
>> loop rather than just the switch.  Hardly an improvement!
>   This is not a valid analogy.  In C, the case statement *requires* the
>   use of a restricted GOTO in order to accomplish "normal" processing;

But we aren't talking about using the "break" in this sense, we are talking
about using the "break" to exit an "if", something which isn't C.

> In other words, C requires use [of] a dangerous construct on a routine basis.

Just as Ada requires the use of "exit" to leave the "loop" construct;
unless you use Ada'a "goto"...

>   With the if construct in C, the default is to exit the if construct 
>   automatically, as opposed to continuing on to execute the section of
>   code associated with the else part.  Thus, we have an inconsistency
>   in C's design: with one flow-of-control construct... use(s) dangerous
>   GOTO [normally] whereas a similar flow-of-control construct... default is
>   reversed.  Given such a language design, it should not surprise anyone
>   that programmers become confused, particularly when the constructs are
>   being used together. 

This argument applies equally to Ada's "loop" construct versus Ada's
"if" construct.

>   Ada, on the other hand, is consistent: in both the if and case statements,

Ignoring the example presented (Ada's loop and exit).

>   the default is to exit the construct once the code associated with the
>   specified situation has been executed.  Ada also provides the exit
>   statement, a restricted GOTO which permits a loop to be exited early,
>   but this construct is not used (as is C's break) on a routine basis.  

Unless one uses the "loop" statement on a routine basis.  Bill may not, but
what if I do?  And if the reversed sense is such a bad example of
program language design, then Ada is an example of bad program
language design.  

I'm not trying to tag Ada, or praise C, but simply to make the point that
this case is *not* an example of error a language such as C or Ada 
detects.  Both programs are legal, both will compile, both are wrong.
Neither C nor Ada are free of flaws.  However, C has not made claims
such as the one which follows:

>   However, we cannot disregard that fact that Ada was
>   specifically designed to provide maximal support for the software 
>   engineering process.

I agree.

However, Ada doesn't pass the test in this case.  It is possible (nay,
inevitable) that someone will misuse the Ada exit statement.  And it is
likely that someone will correctly use the exit statment
in exactly this fashion.  Too bad you can't tell till runtime.



----
jnixon@atl.ge.com                    ...steinmetz!atl.decnet!jnxion

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/22/90)

From jnixon@andrew.ATL.GE.COM (John F Nixon):
>>   This is not a valid analogy.  In C, the case statement *requires* the
>>   use of a restricted GOTO in order to accomplish "normal" processing;
> 
> But we aren't talking about using the "break" in this sense, we are talking
> about using the "break" to exit an "if", something which isn't C.

   We are talking about using a restricted GOTO to exit a control structure
   in a normal situation.  The fact that one type of C control structure
   requires use of a GOTO for normal exit and another type of C control
   structure does not is a source of inconsistency and potential confusion.
   
>> In other words, C requires use [of] a dangerous construct on a routine basis.
> 
> Just as Ada requires the use of "exit" to leave the "loop" construct;
> unless you use Ada'a "goto"...

   Not true; the bare "loop...end loop" is used in situations in which 
   the intention is for the loop to execute forever.  This arises in
   embedded controllers, operating systems, and similar applications.  
   If one is not writing such applications, then "while (Condition) loop"
   and "for Control_Variable in Start..Finish loop" are normally applied. 

   By requiring the use of a GOTO during normal processing (as C does
   with its switch..break system), C encourages its programmers to get 
   into the habit of using its restricted GOTO routinely.  As AT&T has
   recently discovered, that can easily prove to be an expensive habit. 


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

machaffi@fred.cs.washington.edu (Scott MacHaffie) (02/22/90)

In article <8103@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>   the NEXT case.  In other words, C requires the programmer to use a
>   dangerous construct on a routine basis.

(the dangerous construct is the "break" statement)
But if "break" were renamed "end case" then there wouldn't be any problem?

>   code associated with the else part.  Thus, we have an inconsistency
>   in C's design: with one flow-of-control construct (the switch), it is
>   necessary to use a dangerous GOTO to achieve normal processing, whereas

No, it is necessary to use a statement to indicate that the current case
statement is finished...like an "end case" or the next "when => " in ADA.

>   with a similar flow-of-control construct (the if-else), the default is
>   reversed.  Given such a language design, it should not surprise anyone
>   that programmers become confused, particularly when the constructs are
>   being used together. 

Some programmers become confused -- good programmers, and software engineers,
don't.

>   specified situation has been executed.  Ada also provides the exit
>   statement, a restricted GOTO which permits a loop to be exited early,
>   but this construct is not used (as is C's break) on a routine basis.  

In all the ADA I have seen, the preferred looping construct is a "loop"
with exit statements sprinkled throughout it. On the other hand, C's
"break" statement is only occasionally used to exit a loop prematurely.

>> In my limited experience the cases where Ada is introduced into a
>> programming environment also introduce lots of other good software
>> engineering practices.  For example, lots of people I know who
>> program in C don't use LINT.   I view it as a deficiency of management
>> and not of the language that they don't use available tools.

I don't use LINT. I use compilers that check certain things I want checked,
like "no prototypes in scope".  LINT does not catch the kinds of mistakes
that I make.  How many ADA programmers do you know of use LINT?

>   This is certainly true; Brooks and others have noted that the good
>   software engineering practices which are routinely introduced in
>   conjunction with the Ada language are responsible for more of the 
>   resulting improvements than the fact that the Ada language was

Well, these practices are certainly NOT being introduced in the universities
(at least not here).

>   introduced.  However, we cannot disregard that fact that Ada was
>   specifically designed to provide maximal support for the software 
>   engineering process.  C, on the other hand, was designed to provide

No, ADA was designed to have everything. The fact that it (or some subset
of it) can be used to do software engineering doesn't mean it was designed
to do it.  Software engineering can be done in any language, including C.

>   maximal support for the compilation process.  Since compilers and 
>   the CPU power required to operate them come far more cheaply than 
>   programmers, and especially in view of the fact that better error
>   prevention is worth much more than faster compilation, it would seem
>   that the tradeoff made by Ada is certainly the one to be preferred.

The "tradeoff made by ADA?" Do you mean poor code generation versus code that
can be read by non-programmers? Or do you mean the language syntax that
creates nightmares for maintenance? (Does Ada allow you to redefine the
precedence of operators?) Or maybe you mean "language that the government
will use" versus "language that non-government related software companies
will use"?

		Scott MacHaffie

jnixon@andrew.ATL.GE.COM (John F Nixon) (02/22/90)

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) writes:
>From jnixon@andrew.ATL.GE.COM (John F Nixon):
>>>   This is not a valid analogy.  In C, the case statement *requires* the
>>>   use of a restricted GOTO in order to accomplish "normal" processing;
>> But we aren't talking about using the "break" in this sense, we are talking
>> about using the "break" to exit an "if", something which isn't C.
>   We are talking about using a restricted GOTO to exit a control structure
>   in a normal situation.  The fact that one type of C control structure
>   requires use of a GOTO for normal exit and another type of C control
>   structure does not is a source of inconsistency and potential confusion.

Which is also present in Ada, the language designed to maximally support the
software engineering process.

The fact is that one type of Ada control structure requires use of a GOTO
for normal exit and another type of Ada control structure does not is
a source of inconsistency and potential confusion.

>>> ... C requires use [of] a dangerous construct on a routine basis.
>> Just as Ada requires the use of "exit" to leave the "loop" construct;
>> unless you use Ada'a "goto"...
>   Not true; the bare "loop...end loop" is used in situations in which 
>   the intention is for the loop to execute forever.  This arises in
>   embedded controllers, operating systems, and similar applications.  
>   If one is not writing such applications, then "while (Condition) loop"
>   and "for Control_Variable in Start..Finish loop" are normally applied. 

Then why provide the exit statement at all?  I refer you to the statements
above which describe the confusion this situation can produce.

*If* the designers of Ada had intended "loop" to be used exclusively for
forever loops, they would not have provided an "exit" from the loop.
Since they *did* choose to provide "exit", I must assume it was a deliberate
and reasoned choice which would maximally support the software engineering
process.  Given that, it is hard to ding the C use without dinging Ada use.
Therfore, there exist language constructs within Ada which "[are] a
source of inconsistency and potential confusion", or it isn't such a
terrible thing after all.

Are there plans in Ada-9X to remove the confusing "exit" construct?
(and where can one obtain the Ada-9X proposals?  I would be interested
in learnig more about the modifications to Ada)
Do you know of any other Ada constructs which are bad software
----
jnixon@atl.ge.com                    ...steinmetz!atl.decnet!jnxion

pierson@encore.com (Dan L. Pierson) (02/23/90)

In article <5017@csv.viccol.edu.au> dougcc@csv.viccol.edu.au (Douglas Miller) writes:
   Valid but utterly vacuous point, as ADA *was* designed to provide maximal
   support for software engineering.  I suppose its possible that another
   (hidden?) design goal was to "have everything".  So what?

   >    Software engineering can be done in any language, including C.

   Irrelevant --- the claim here is that ADA provides *maximal* *support* for
   the software engineering process.  Like, if I said "Air travel is the
   fastest way to get to another city" and you said "You don't have to go by
   `plane.  You could go by car, or even on foot", then I'd look at you with a
   slightly glazed expression, right?   Sorry to labor this, but I've seen the
   above point made *too* many times.

This bit of ADA mythology (or dogma) has also been made too many times
for me to remain silent.  Yes, ADA did have a goal of maximal support
for the software engineering process.  However other goals (and the
committee requirements and design process) largely subverted that goal
by producing an excessively large, over-specified monster.

You can certainly do software engineering in ADA, it is in most ways a
better language for the purpose than C, but other languages such as
Modula-3, Eiffel, and maybe Turing provide at least the software
engineering benefits of ADA (though not all the "nifty" features*) in
languages that are small enough to be useable, learnable, teachable,
and efficiently implementable in less than a decade.

I'm not interested in another C vs. ADA vs. my-favorite-language war,
but I'm just plain tired of the line that ADA is equivalent to
software engineering because the DOD and those who base their careers
on it say so.

*In fact, some of these "nifty" features present more opportunity for
misuse, and thus software engineering drawbacks, than benefits.
Operator overloading comes to mind...
--

                                            dan

In real life: Dan Pierson, Encore Computer Corporation, Research
UUCP: {talcott,linus,necis,decvax}!encore!pierson
Internet: pierson@encore.com

rkl@cbnewsh.ATT.COM (kevin.laux) (02/23/90)

In article <8111@hubcap.clemson.edu>, billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) writes:
| From jnixon@andrew.ATL.GE.COM (John F Nixon):
| >>   This is not a valid analogy.  In C, the case statement *requires* the
| >>   use of a restricted GOTO in order to accomplish "normal" processing;
| > 
| > But we aren't talking about using the "break" in this sense, we are talking
| > about using the "break" to exit an "if", something which isn't C.
| 
|    We are talking about using a restricted GOTO to exit a control structure
|    in a normal situation.  The fact that one type of C control structure
|    requires use of a GOTO for normal exit and another type of C control
|    structure does not is a source of inconsistency and potential confusion.
|    
| >> In other words, C requires use [of] a dangerous construct on a routine basis.
| > 
| > Just as Ada requires the use of "exit" to leave the "loop" construct;
| > unless you use Ada'a "goto"...
| 
|    Not true; the bare "loop...end loop" is used in situations in which 
|    the intention is for the loop to execute forever.  This arises in
|    embedded controllers, operating systems, and similar applications.  
|    If one is not writing such applications, then "while (Condition) loop"
|    and "for Control_Variable in Start..Finish loop" are normally applied. 
| 
|    By requiring the use of a GOTO during normal processing (as C does
|    with its switch..break system), C encourages its programmers to get 
|    into the habit of using its restricted GOTO routinely.  As AT&T has
|    recently discovered, that can easily prove to be an expensive habit. 

	For some reason this is starting to annoy me.  All this talk about
'dangerous' GOTOs, restricted GOTOs, etc.  The bottom line is that the
program was coded *wrong*, whatever the language used.  Reminds me of the
phrase "the program should do what I wanted, not what I told it...".

	Anyway, as for the stigma of using GOTOs, way back when, I fell for
the line of bull about GOTOless programming.  I changed my mind real quick
for two reasons:  1) when I found myself in a situation where I *had* to use
a GOTO (break all the way out from inside of two loops) and 2) when I looked
at the assembly language generated by the compiler.  Turns out that when
an IF is employed, the compiler will often generate a test that is the
of the reverse sense and will then perform a conditional branch (gee, a
restricted GOTO).

	So, if you take a look at the machine language generated by your
C program, you'll find it littered with lots of conditional and unconditional
jumps.  The difference we're talking about is the *explicit* use of jumps
by the programmer (and not the implicit ones hidden by the language).

	GOTOs are not inherently dangerous contructs.  *Abuse* of them is.
Lastly I don't find that fact that one C control structure requires a GOTO
(via break) for 'normal' exit versus one that does not to be any source of
confusion.  SWITCH..BREAK is very well documented.

--rkl

jnixon@andrew.ATL.GE.COM (John F Nixon) (02/23/90)

jnixon@andrew.ATL.GE.COM (John F Nixon)[that's me] writes:
>(and where can one obtain the Ada-9X proposals?  I would be interested
>in learnig more about the modifications to Ada)
>Do you know of any other Ada constructs which are bad software

... engineering examples.  

Whoops, wrong group!  Sorry, for a moment I thought I was in c.l.ada...

--

----
jnixon@atl.ge.com                    ...steinmetz!atl.decnet!jnxion

grimlok@hubcap.clemson.edu (Mike Percy) (02/23/90)

From article <8103@hubcap.clemson.edu>, by billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ):

[Ada is great, Ada is wonderful, nothing can beat Ada, if you don't program 
 in Ada you are stupider than worm-slime, blah blah blah]

I've used Ada Bill, I even liked it. But, I am really getting tired of reading
your diatribes against every other programming language, of reading your
praises of Ada to the exclusion of all others.  I use the language I feel
is best for the particular problem at hand.  I drop into assembly to 
optimize a speed-critical section of code.  I use C for portability (right,
I know, there are n fully verified  Ada compilers running of x different
machines, so how can Ada not be portable?) and speed of coding (my speed
is higher in C than in Ada or any other language, this is subject to
change of course), I use COBOL at work because that is the language the
systems I maintain, I use a quasi-4GL when I can to spit out 3GL code. 
SOmetimes I use SNOBOL, Lisp, or Prolog, or Pascal.

I've seen some Ada code that must have been written by brain-damaged idiots.
And I've seen some beautifully written assembly.

The point is, that the programming practices are what makes the difference.
It is entirely reasonable to engineer software in C or Prolog or...
Just as it is reasonably easy to mangle Ada.  Granted, Ada lends itself
to good software engineering practices, probably you could even say that it
encourages it. However, it does not guarantee it, nor does the failure to
use Ada preclude good software engineering practices.

My guess is that Ada will gain a load of users and their respect when there 
is a Microsoft Ada or better yet (or worse yet) a Turbo Ada.

Anyway please try to keep your pro-Ada, anti-everything-else stuff in check. 

-- 

'I just couldn't convince the voters that Dukakis was Greek for
"Bubba".' -- Lloyd Benson explaining why the Democrats didn't carry
Texas

mjones@fenway.uucp (Mike Jones) (02/23/90)

In article <8111@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>   By requiring the use of a GOTO during normal processing (as C does
>   with its switch..break system), C encourages its programmers to get 
>   into the habit of using its restricted GOTO routinely.  As AT&T has
>   recently discovered, that can easily prove to be an expensive habit. 

Ah, I see it now. The problem here is that you keep insisting that the
use of break in switch statements is "normal processing". "Common" it
certainly is, but the very purpose of break is to *change* "normal"
processing. The switch statement in C is NOT equivalent to an 
if...else if...else statement group. It is common practice to use the
break statement to make it behave that way. Is this a design flaw? Quite
possibly, but it's not the same flaw you're claiming.
Mike Jones		|  The basic state of software development is that
AIX Development		|  we're all eating raw food because no one has the
Kingston, NY		|  time to learn how to cook.
.!uunet!ibmps2!aix!mjones

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/23/90)

From jnixon@andrew.ATL.GE.COM (John F Nixon):
>>>> ... C requires use [of] a dangerous construct on a routine basis.
>>> Just as Ada requires the use of "exit" to leave the "loop" construct;
>>> unless you use Ada'a "goto"...
>>   Not true; the bare "loop...end loop" is used in situations in which 
>>   the intention is for the loop to execute forever.  This arises in
>>   embedded controllers, operating systems, and similar applications.  
>>   If one is not writing such applications, then "while (Condition) loop"
>>   and "for Control_Variable in Start..Finish loop" are normally applied. 
> 
> Then why provide the exit statement at all?  

   Suppose that one is in a for loop or a while loop, and some
   unusual situation arises under which processing cannot continue.
   The exit statement allows one to conveniently handle such cases.

> (and where can one obtain the Ada-9X proposals?  

   Simply dial up the Ada 9X bulletin board at (301) 459-8939.


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/23/90)

From machaffi@fred.cs.washington.edu (Scott MacHaffie):
>>   code associated with the else part.  Thus, we have an inconsistency
>>   in C's design: with one flow-of-control construct (the switch), it is
>>   necessary to use a dangerous GOTO to achieve normal processing, whereas
> 
> No, it is necessary to use a statement to indicate that the current case
> statement is finished...like an "end case" or the next "when => " in ADA.

   Such a statement already exists: either the next "case Value:", or 
   the } which ends the switch.  Why is it necessary to use a "break"?
 
>>   with a similar flow-of-control construct (the if-else), the default is
>>   reversed.  Given such a language design, it should not surprise anyone
>>   that programmers become confused, particularly when the constructs are
>>   being used together. 
> 
> Some programmers become confused -- good programmers, and software 
> engineers, don't.

   The problem cannot simply be defined out of existence by saying,
   in essence, that good programmers don't make mistakes.  All human
   programmers make mistakes, and a well-designed language will help
   to minimize this particular tendency.  In this case, C does not. 

>>   This is certainly true; Brooks and others have noted that the good
>>   software engineering practices which are routinely introduced in
>>   conjunction with the Ada language are responsible for more of the 
>>   resulting improvements than the fact that the Ada language was
> 
> Well, these practices are certainly NOT being introduced in the 
> universities (at least not here).

   In that case, I strongly suggest that you immediately bring 
   this fact to the attention of the software engineering faculty 
   at washington.edu.  At other universities (e.g., Clemson), Ada
   *is* introduced in conjunction with software engineering.


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

lawhorn@optis31.uucp (Jeff Lawhorn) (02/23/90)

It seems to me that if the program in question had been
thoroughly tested it would not matter if it had been written in
C or Ada or Pascal or anything else.  The bug would have been
found, and AT&T's network would not have been knocked off the
air.  In **EVERY** language it is possible to write valid code
that does not do what the programmer wants.  This is why every
possible code path should be tested before it is placed into a
production system.  Let's hope that AT&T didn't learn not to use
C or Ada or whatever, but that they learned to test their
software better before using it in a production system.
--
Jeff Lawhorn
lawhorn@opti.uucp
opti!lawhorn@berick.uucp
ucsd!sdsu!berick!opti!lawhorn

john@stat.tamu.edu (John S. Price) (02/23/90)

In article <8124@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>> Then why provide the exit statement [in Ada] at all?  
>
>   Suppose that one is in a for loop or a while loop, and some
>   unusual situation arises under which processing cannot continue.
>   The exit statement allows one to conveniently handle such cases.
>

Suppose, in C, that one is in a for loop or a while loop, and
some unusual situation arises under which processing cannot continue.
The break statement allows one to conveniently handle such cases.

But, really, folks, what is the difference between

...
switch(x)
{
  case a: ... break;
  case b: ... break;
}
...

and

...
case foo is
  when x => ...
  when y => ...
...

(I think I remember my Ada correctly... if not, please, it's close enough)?

The control structures case/when have to be terminated somehow.
In Ada, it is terminated by the next when statement.  In C, it's
terminated by a break statement.  Just deal with it.  

Personally, I've found some nice uses of NOT putting a break in
a switch statement, when I have two similiar cases, but one has a
little bit more processing that needs to be done...

This is a *C* newsgroup.  Why talk about the merits and disadvantages
of Ada?  Take it to comp.lang.ada, if there is one.  People like
C.  Who is anyone to tell them (including me) that their opinion is
wrong, or that their preference is wrong?

Give it a rest.

>
>   Bill Wolfe, wtwolfe@hubcap.clemson.edu


--------------------------------------------------------------------------
John Price                   |   It infuriates me to be wrong
john@stat.tamu.edu           |   when I know I'm right....
--------------------------------------------------------------------------

dougcc@csv.viccol.edu.au (Douglas Miller) (02/23/90)

In article <10811@june.cs.washington.edu>, machaffi@fred.cs.washington.edu (Scott MacHaffie) writes:
> In article <8103@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>>   introduced.  However, we cannot disregard that fact that Ada was
>>   specifically designed to provide maximal support for the software 
>>   engineering process.  C, on the other hand, was designed to provide
> 
> No, ADA was designed to have everything.  The fact that it (or some subset
> of it) can be used to do software engineering doesn't mean it was designed
> to do it.

Valid but utterly vacuous point, as ADA *was* designed to provide maximal
support for software engineering.  I suppose its possible that another
(hidden?) design goal was to "have everything".  So what?

>    Software engineering can be done in any language, including C.

Irrelevant --- the claim here is that ADA provides *maximal* *support* for
the software engineering process.  Like, if I said "Air travel is the
fastest way to get to another city" and you said "You don't have to go by
`plane.  You could go by car, or even on foot", then I'd look at you with a
slightly glazed expression, right?   Sorry to labor this, but I've seen the
above point made *too* many times.

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/23/90)

From mjones@fenway.uucp (Mike Jones):
>>   By requiring the use of a GOTO during normal processing (as C does
>>   with its switch..break system), C encourages its programmers to get 
>>   into the habit of using its restricted GOTO routinely.  As AT&T has
>>   recently discovered, that can easily prove to be an expensive habit. 
> 
% Ah, I see it now. The problem here is that you keep insisting that the
% use of break in switch statements is "normal processing". "Common" it
% certainly is, but the very purpose of break is to *change* "normal"
% processing. The switch statement in C is NOT equivalent to an 
% if...else if...else statement group. It is common practice to use the
% break statement to make it behave that way. Is this a design flaw? Quite
% possibly, but it's not the same flaw you're claiming.

   On the contrary, this is precisely the flaw I'm pointing out!!!

   C's switch statement is badly designed, so badly designed that it is 
   common practice to use break statements by the dozen in order to get 
   it to behave reasonably.  A more sensible design would give the switch 
   the semantics of the Ada case statement, thereby saving countless lines 
   of code through the elimination of all those "break" statements. 


   Bill Wolfe, wtwolfe@hubcap.clemson.edu
 

ok@goanna.oz.au (Richard O'keefe) (02/23/90)

There's been a lot of discussion about the "switch" statement.
What people seem to have missed is that there are TWO debatable
features about C's "break" statement, one of which was NOT
present in C's grandfather BCPL.

One debatable feature about "break" is that it is not automatically
implied at the end of every case.  That means that you can leave it
out when you didn't mean to.  There are several ways of dealing
with the problem.  One would be to use an editor macro which does
	insert "case :"
	create new line indented one more step
	insert "break;"
	move back to just before the ":"
That would make it easy to terminate your cases properly.
Another approach would be to add an option to "lint" to warn about
missing "breaks;", the warning would be produced whenever one case
fell through into the next and could be suppressed by a /*FALLTHROUGH*/
comment.  (Never mind GCC, what _I_ want is a GLINT.)

But from the rather garbled problem description which triggered off
this thread, that wasn't the problem.  The problem is that C uses
"break" for two very different things:  finishing a case in a switch,
and exiting from a loop.  I've lost count of the number of times I have
had to add a label, use a 'return', or restructure my program simply
because the place where I wanted to put a loop 'break' was inside a
switch.  The real pity of it is that BCPL used two different keywords
for these two different operations.  The one for finishing a case was
ENDCASE.  C inherited most of its control structures from BCPL.  I
have long wondered why C's (or B's, whichever) designers went out of
their way to introduce this problem.

	

bitbug@lonewolf.sun.com (James Buster) (02/23/90)

In article <8133@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) writes:
> C's switch statement is badly designed, so badly designed that it is 
> common practice to use break statements by the dozen in order to get 
> it to behave reasonably.  A more sensible design would give the switch 
> the semantics of the Ada case statement, thereby saving countless lines 
> of code through the elimination of all those "break" statements. 
>
> Bill Wolfe, wtwolfe@hubcap.clemson.edu

I claim that the possibly erroneous replication of code required by the Ada
case statement, e.g.

-- in approximate Ada style
switch foo is
    case 5 =>
	statement1;
	statement2;
	statement3;
    case 7 =>
	statement1;
	statement2;
	statement3;
end

as compared too C's

switch (foo)
{
    case 5:
    case 7:
	statement1;
	statement2;
	statement3;
}

is well worth remembering to put in break statements.
--
---------------------------------------------------------------------
        James Buster		(Domain) bitbug@lonewolf.ebay.sun.com
  Mad Hacker Extraordinaire	(UUCP)   ...!sun.com!lonewolf!bitbug
---------------------------------------------------------------------

machaffi@fred.cs.washington.edu (Scott MacHaffie) (02/23/90)

In article <8126@hubcap.clemson.edu% billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
%From machaffi@fred.cs.washington.edu (Scott MacHaffie):
%% No, it is necessary to use a statement to indicate that the current case
%% statement is finished...like an "end case" or the next "when =% " in ADA.
%
%   Such a statement already exists: either the next "case Value:", or 
%   the } which ends the switch.  Why is it necessary to use a "break"?

example:
	switch (x) { /* x is a character, for example */
		case '0': case '1': ... case '9':
			print_digit(x);
			break;
		case 'a': ... case 'z':
			print_lowercase(x);
			break;
	}
The semantics of a C switch/case statement are different than the semantics
of an ada case/when.

%   The problem cannot simply be defined out of existence by saying,
%   in essence, that good programmers don't make mistakes.  All human
%   programmers make mistakes, and a well-designed language will help
%   to minimize this particular tendency.  In this case, C does not. 

Good programmers understand the language they are using -- good programmers
are literate. No language can eliminate errors. Good software engineering
practices should be used to (try to) catch language-specific errors.

%%%   This is certainly true; Brooks and others have noted that the good
%%%   software engineering practices which are routinely introduced in
%%%   conjunction with the Ada language are responsible for more of the 
%%%   resulting improvements than the fact that the Ada language was
%% 
%% Well, these practices are certainly NOT being introduced in the 
%% universities (at least not here).
%
%   In that case, I strongly suggest that you immediately bring 
%   this fact to the attention of the software engineering faculty 
%   at washington.edu.  At other universities (e.g., Clemson), Ada
%   *is* introduced in conjunction with software engineering.

Software engineering faculty?  I wish. None of the undergraduate classes
here touch software engineering, and I think at most one of the graduate
classes does. Anyone who wants to be a software engineer here has to
pick it up from other sources.

			Scott MacHaffie

machaffi@fred.cs.washington.edu (Scott MacHaffie) (02/23/90)

In article <8133@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>   common practice to use break statements by the dozen in order to get 
>   it to behave reasonably.  A more sensible design would give the switch 
>   the semantics of the Ada case statement, thereby saving countless lines 
>   of code through the elimination of all those "break" statements. 

But it would also ADD countless lines of code:

ANSI C:
switch (x) {
	case '0': case '1': ... case '9':
		digit(x);
		break;
}

ADA-C:
switch (x) {
	case '0': digit(x);
	case '1': digit(x);
	...
	case '9': digit(x);
}
		Scott MacHaffie

ok@goanna.oz.au (Richard O'keefe) (02/23/90)

In article <4582@jarthur.Claremont.EDU>, jseidman@jarthur.Claremont.EDU (James Seidman) writes:
: In article <2903@goanna.oz.au> ok@goanna.oz.au (Richard O'keefe) writes:
: >One debatable feature about "break" is that it is not automatically
: >implied at the end of every case.  That means that you can leave it
: >out when you didn't mean to.  There are several ways of dealing
: >with the problem...
: 
: It's interesting how this goes from a "debatable feature" to a "problem" in
: three sentences.

It's interesting how many people have difficulty reading English.
"the problem" refers to "leaving a break out when you didn't mean to",
not to the break statement as such.

Let me say this one more time in words that have but one sound in them
save for the text which I quote from my last:

	If you want a case in C to stand on its own and not fall through
	to the next case, you must write the 'break' sign, not C, for C
	deems it the norm for a case to fall through to the next save
	when you make it quite clear that you do not want this.
	[*this* is the "debatable feature"]
	To the woe of a great host of those who write in C, what C deems
	the norm is rare, and oft we slip and leave the 'break' sign out.
	We get a text which C likes well, which does not do what we want,
	but where it is hard to see what we did wrong.
	[*this* is the "problem"]

	WE DO NOT NEED TO CHANGE C TO SHUN THE SNARE;
	we have but to add to the tools we use to write C.

Now, why did a *positive* claim about C, a suggestion that C isn't
badly enough broken to warrant fixing, elicit an attack?


: This argument seems to me about equivalent to saying "One
: of the debatable features about 'if' is that a new program block is not
: defined.  That means that you can have a statement which you meant to have
: in the if statement but isn't."  You know, something like
:   if (a == b)
: 	bar(a);
: 	foo(a);
:   a++;
: Do you propose making an editor macro to handle ifs to prevent this?

Some sort of tool YES.  And such a tool exists.  It's called "indent".
I don't have this problem, because I use
	if (test) stmt-on-same-line;
if it's a single statement which will fit on the same line, or
	if (test) {
	    stuff that won't fit on one line
	}
otherwise, so the mistake can't happen.  But I find that it _always_
pays me to run indent on other peoples' code precisely to catch this
kind of mistake.  I've met people with an editor key bound to
	insert "if () {"
	insert a new line at the same indentation level
	insert "}"
	go back to just after the "("

: The fact that some people have trouble
: remembering to put a "break" in the right place isn't a problem with the
: language, it's a problem with the programmer.

If a few people had the problem, it would be a problem with them.
When a LOT of people have the problem, it's a problem with the language.
My attitude is that saying "C is perfect" is just as futile as saying
"I wish C were exactly the way I'd like it", and that what we should be
doing in this newsgroup is suggesting ways of reducing known risks.
For example, I posted a tool a year or two ago for finding comments that
go on longer than you expected (it just copies the file to the terminal,
displaying comments highlighted).

: According to K&R (2nd ed.), "A break causes the innermost enclosing loop or
: switch to be exited immediately." (p. 64) 

So?  We all knew that.  

: {an example of a for inside a switch deleted}
: I haven't compiled this particular example, but I have done things
: like this many times with Turbo-C, MS-DOS msc 5.0, gcc, and BSD 4.2 cc.  I
: don't know what platform you're running that has such a nonstandard form of
: C that it doesn't work like this.

What on earth are you on about?  What I wrote was that I have run into
trouble with a switch inside a loop (not a loop inside a switch) where
I wanted to exit the loop but the switch captured the break.  I'm not
talking about any nonstandard C, but the simple fact that 

	for (...) {
	    switch (...) {
		case...
		    ...
			/* now I want to exit the LOOP */
				
(a) can't be done without introducing a goto or return, or rewriting
    the code.
(b) is risky because if you put a 'break' there _thinking_ it will
    terminate the loop the compiler will happily accept it but do
    something else (this is particularly risky when you turn an
    existing 'if' into a 'switch')

: I don't see why you think there need to be two separate functions to do the
: same thing.

I don't.  Heck, 'goto' will do the job just fine.  The point I raised
is that the grandparent of C *DID NOT HAVE THIS PROBLEM*.  It's not a
risk which was introduced into C because the designers didn't happen to
think of it.  In BCPL it is perfectly safe to turn an 'if' into a
'switch' because BREAK statements continue to refer to the same loop
that they referred to before, cases must be ended with ENDCASE.


: The behavior [of break] is unambiguous and consistent.

Indeed and it is.  It is also confusing and risky.
To cite an example from another programming language, the "cut"
operation in Prolog is unambiguous and consistent and from one point
of view does a single thing.  It is also notoriously a source of
confusion and error.

I stand by my suggestions that
    - if you have trouble with forgetting 'break' in switches,
      consider writing an editor macro to insert the 'break' with
      the 'case'
    - a tool that checks for missing 'break's would be useful; a
      lint option would be ideal but
	cc -E prog.c | {check for "case" or "default" not preceded
	by "{", ":", "return ...;" or "break;"}
      might be useful.
and my question
    - given that BCPL separated "quit a case" (ENDCASE) from
      "leave a loop" (BREAK), why did C conflate them?

bethge@wums.wustl.edu (Paul H. Bethge) (02/24/90)

In article <10839@june.cs.washington.edu>, machaffi@fred.cs.washington.edu
(Scott MacHaffie) writes:
> In article <8133@hubcap.clemson.edu>
> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>>   common practice to use break statements by the dozen in order to get 
>>   it to behave reasonably.  A more sensible design would give the switch 
>>   the semantics of the Ada case statement, thereby saving countless lines 
>>   of code through the elimination of all those "break" statements. 
> 
> But it would also ADD countless lines of code:
> 
> ANSI C:
> switch (x) {
> 	case '0': case '1': ... case '9':
> 		digit(x);
> 		break;
> }
> 
> ADA-C:
> switch (x) {
> 	case '0': digit(x);
> 	case '1': digit(x);
> 	...
> 	case '9': digit(x);
> }

Oh, come *ON*!  The situation  where  several  cases  need  to  do
exactly the same thing could easily be handled by a syntax such as
switch (x) {
	case '0', case '1', ... case '9':
		digit(x);
	. . .
}

The only real utility of the fall-through feature  of  the  switch
statement  is  in  the  situation  where  several cases need to do
*almost* the same thing, but some of the cases need to do a little
more  than  others.   This  is  clearly  going  to be a very small
fraction of the uses of the switch statement.

C is not perfect, and it does not need to be perfect to be useful.
No  one is proposing to *change* the switch statement; we are just
sighing about what-might-have-been.

BTW, does not the C switch statement closely resemble the  Fortran
computed  GOTO?  (Sorry, I couldn't help myself.  Please flame via
e-mail; I get lonely sometimes. Oh, yeah :-) :-) :-)

__________________________________________________________________
Paul H. Bethge                               bethge@wums.wustl.edu
Biochemistry, Box 8231                          bethge@wums.bitnet
Washington University
St. Louis, MO 63110                                   314-362-3354

peter@ficc.uu.net (Peter da Silva) (02/24/90)

With apologies to all the people tired of Bill Wolfe's Adaphilic C-bashing,
the people arguing that you *need* break are all wet. Observe:

	switch(c)
	{
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			digit();
		default:
			not_a_digit();
	}

On the other hand, the people (inlcuding Bill) arguing that switch...break
is an unalloyed disaster are also all wet.  The C SWITCH is not a Pascal
CASE, it's a computed goto:

	switch(c)
	{
		case '%':
			stuff...
			break;
		case '$':
			stuff...
			break;
		case '\\':
			nextc = getchar();
			if(nextc == '%' || nextc == '$')
				c = nextc;
			else
				ungetc(nextc, stdin);
			/* FALLTHROUGH */
		default:
			lots...
			of...
			stuff...
			break;
	}

The right solution for Next C (whether it be P or D) is to defang break
by using a different keyword for breaking from a switch or exiting from
a loop. I would suggest that 'break' be given a mandatory keyword argument:
either 'break switch', 'break for', and so on.
-- 
 _--_|\  Peter da Silva. +1 713 274 5180. <peter@ficc.uu.net>.
/      \
\_.--._/ Xenix Support -- it's not just a job, it's an adventure!
      v  "Have you hugged your wolf today?" `-_-'

henry@utzoo.uucp (Henry Spencer) (02/24/90)

You know, this C-vs-Ada-control-structures argument is totally pointless
and deadly boring.  Neither language is ideal, but neither is fatally
flawed, and the differences between *programmers* are so large that they
totally swamp differences between *languages* in most practical situations.
Languages cannot save you from yourself except in relatively minor ways.
Despite repeated attempts (including Ada) to develop languages in which
it would be impossible to write bad programs, the bad programmers have
consistently, and usually fairly easily, found ways to continue making
their messes.

Give it a rest, guys.
-- 
"The N in NFS stands for Not, |     Henry Spencer at U of Toronto Zoology
or Need, or perhaps Nightmare"| uunet!attcan!utzoo!henry henry@zoo.toronto.edu

mph@lion.inmos.co.uk (Mike Harrison) (02/24/90)

In article <5017@csv.viccol.edu.au> dougcc@csv.viccol.edu.au (Douglas Miller) writes:
>Valid but utterly vacuous point, as ADA *was* designed to provide maximal
>support for software engineering.  I suppose its possible that another
>(hidden?) design goal was to "have everything".  So what?
>
Wrong ! - Ada was designed primarily to save DoD money, secondarily to support
very long in-service life software (by simplifying the maintenance process), 
with all kinds of other goodies as a tertiary aim.

Way back in (about) 1975 HOLWG showed that DoD was spending huge sums on s/w 
in embedded systems, which were programmed in >300 languages (including ~ 70
different, often incomptible versions of JOVIAL).
The idea of Ada (was Ironman etc.) was to provide a *single* language in which
almost all embedded operational military s/w would be written, then it would 
only be necessary to keep one kind of programmer - an Ada programmer.

Those of us working on Ada and its environments (things which led to Stoneman)
in those days were serious about this people portablity (which was the prime
motivation for the NO SUBSETS, NO SUPERSETS policy).

Whether Ada, its implementers, DoD or anyone else succeded in these aims is a
matter of personal taste, but I believe that the aims were good and the spirit
which motivated most of the early workers was laudable.

[Whatever became of paths and boxes?]

Mike,




Michael P. Harrison - Software Group - Inmos Ltd. UK.
-----------------------------------------------------------
UK : mph@inmos.co.uk             with STANDARD_DISCLAIMERS;
US : mph@inmos.com               use  STANDARD_DISCLAIMERS;

oplinger@proton.crd.ge.com (B. S. Oplinger) (02/24/90)

Consider the following (slightly modified from the example by Scott MacHaffie):

example:
        switch (x) { /* x is a character, for example */
                case '0': 
                        number_of_groups ++;
                case '1': ... case '9':
                        print_digit(x);
                        break;
                case 'a': ... case 'z':
                        print_lowercase(x);
                        break;
        }


In my example, 0 is just like any other number except that it signals
the start of a new group, hence the increment on the number-of-groups
counter.  This is just the problem with the syntax of the C case
(switch) statement. It is designed so that a case may do some work and
then 'share' the work of the following case statement. I will submit
that this general attitude is found throughout C. Ada, although not a
perfect language, is almost always presented with some discussion on
software-engineering. I feel that this help promote good work habits. 

On LINT, I would never program without it (in C). There is no excuse
for today's language running on todays machines (hell, even the PC)
that LINT checking cannot be done during a compile. I believe that it
should also be an option that must be turned off, not on.

various random thoughts from:

brian
oplinger@crd.ge.com

<#include standard.disclaimer>

schwartz@barad-dur.endor.cs.psu.edu (Scott E. Schwartz) (02/24/90)

In article <BITBUG.90Feb22221658@lonewolf.sun.com> James Buster writes:
>I claim that the possibly erroneous replication of code required by the Ada
>case statement, e.g.
>-- in approximate Ada style
>switch foo is
>    case 5 =>
>	statement1; statement2; statement3;
>    case 7 =>
>	statement1; statement2; statement3;
>end

Ada programmers would write this as:

  case foo is
    when 5 | 7 => statemen1; statement2; statement3;
  end case;

Next strawman?

--
Scott Schwartz		schwartz@cs.psu.edu
"the same idea is applied today in the use of slide rules." -- Don Knuth 

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/24/90)

From bitbug@lonewolf.sun.com (James Buster):
> I claim that the possibly erroneous replication of code 
> required by the Ada case statement, e.g.
> 
% -- in approximate Ada style     as compared to C's
% switch foo is                    switch foo 
%     case 5 =>                    {
% 	statement1;                   case 5: 
% 	statement2;                   case 7:
% 	statement3;                     statement1;
%     case 7 =>                         statement2;
% 	statement1;                     statement3;
% 	statement2;                }
% 	statement3;
% end
> 
> is well worth remembering to put in break statements.

   Until one discovers that Ada enables the following construction:

      case foo is   [...]
         when 5 | 7 =>
            statement1;
            statement2;
            statement3;
      end case; 


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

djones@megatest.UUCP (Dave Jones) (02/24/90)

From article <2903@goanna.oz.au>, by ok@goanna.oz.au (Richard O'keefe):
> There's been a lot of discussion about the "switch" statement.
> What people seem to have missed is that there are TWO debatable
> features about C's "break" statement, one of which was NOT
> present in C's grandfather BCPL.

I'll add a third one. Or maybe it's just a bug in the compiler I use.
I've been programing in C full time for about six years
now, so I don't make many mistakes, but I made this one the other day:

    enum bar { biff, bam, boom };

    proc()
    { enum bar foo;
       /* ... */
       switch(foo) {
       case biff:
          do_this();
          break;
       case bad:
          do_that();
          break;
       boom:
          do_the_other();
          break;
       }
     }

(The cases were separated by more lines of code.) The compiler loved
it. Sun's cc allows this if the enumeration is declared globally, but
not if it is declared within a block, if I remember correctly.

Of course, testing exposed the mistake, and a fellow whom I
asked to "look at this and see what I'm missing," looked at it
and saw what I was missing.

jseidman@jarthur.Claremont.EDU (James Seidman) (02/24/90)

In article <12134@goofy.megatest.UUCP> djones@megatest.UUCP
(Dave Jones) writes:
>    proc()
>    { enum bar foo;
>       switch(foo) {
	[program parts deleted]
>       boom:
>          do_the_other();
>          break;
>       }
>     }
>(The cases were separated by more lines of code.) The compiler loved
>it. Sun's cc allows this if the enumeration is declared globally, but
>not if it is declared within a block, if I remember correctly.

I think, unfortunately, that this is in fact correct code.  It is,
ironically, a "labeled statement," the kind used with goto.  I'm not sure
about why Sun's cc doesn't allow this if the enumeration is declared within
a block, though.  Under ANSI, labels have their own name space which is
independent of enumerations and the like.  I get the impression, though,
that this is not very well standardized on pre-ANSI compilers.  Labeled
statements inside a case statement would be a nice addition to lint,
though.
-- 
-------------------------------------------------------------------------------
Jim Seidman, Harvey Mudd College, Claremont, CA 91711.  (714) 621-8000 x2026
DISCLAIMER: I don't even know if these are opinions, let alone those of
            anyone other than me.

martin@mwtech.UUCP (Martin Weitzel) (02/24/90)

In article <8133@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
[some lines deleted]

>   C's switch statement is badly designed, so badly designed that it is 
>   common practice to use break statements by the dozen in order to get 
>   it to behave reasonably.  A more sensible design would give the switch 
>   the semantics of the Ada case statement, thereby saving countless lines 
>   of code through the elimination of all those "break" statements. 

Though C has a badly designed switch statement (I don't doubt) it has
proven to be a useful language and seems to be in more widespread use
than 'better' ones. What I am missing in this discussion is to see:

	#define when break;case

so that you can write:

	switch(x) {
	default:
	when 1: /*stuff*/
	when 2: /*more stuff*/
	}

(O.K., not quite the ADA syntax, but it should work ...)

BTW: I would *not* like to go into a new round of the discussion
about using the preprocessor to define new "keywords". Everyone
who remembers my articles from the last war on this topic knows,
that I *don't* like to have new keywords. I have made the above
proposual only to heat this debate about good or bad design of
the switch statement :-)

Finally I would like to add another experience with switch:
Some day, I had written the following piece of code:

	enum sound { DING, DONG, DELL } x;
	....
	enum sound getsound()
	{
		....
	}
and later
	.....
	switch (x = getsound()) {
	DING:	/*stuff*/
		break;	<----- No, *this* was not missing
	DONG:	/*other stuff*/
		break;
	DELL:	/*still other stuff*
		break;
	}

Do you see, what is wrong with that?

I did not write "case DING:" aso., so DING: was considered to be a
goto-label (and as such had a different name space as enum names and
the program compiled without errors).

The problem was hard to find because this particular compiler
figured out, that the code within the case statement would never
be excuted (there were no case-label in it!) and optimized the
whole(!) statement away. Of course, this was a little too much
optimization, because the call to getsound() was also optimized
away (buggy compiler). Clearly, it was not at all obvious, why
my program never called getsound(): I did put a printf() right
before and after the switch, which both were executed, but
getsound() never was.

(Today I use #define rather that enum for such things, so that
this problem will not any more occur :-))
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

sommar@enea.se (Erland Sommarskog) (02/25/90)

Scott MacHaffie (machaffi@fred.cs.washington.edu.cs.washington.edu) writes:
)Bill Wolfe (billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu) writes:
))   the NEXT case.  In other words, C requires the programmer to use a
))   dangerous construct on a routine basis.
)
)(the dangerous construct is the "break" statement)
)But if "break" were renamed "end case" then there wouldn't be any problem?
)
))   code associated with the else part.  Thus, we have an inconsistency
))   in C's design: with one flow-of-control construct (the switch), it is
))   necessary to use a dangerous GOTO to achieve normal processing, whereas
)
)No, it is necessary to use a statement to indicate that the current case
)statement is finished...like an "end case" or the next "when =) " in ADA.

I don't speak C, so I might have missunderstood something, but I'm
under the impression that you may exclude the "break" statement
achieving the effect that you execute the code for the next case too.
Sometimes possibly a nifty feature, but it seems to me that is a good
source of errors. Whether it's called "break" or "end case" has no
importance. You may inadvertantly forget it in both cases.

)I don't use LINT. I use compilers that check certain things I want checked,
)like "no prototypes in scope".  LINT does not catch the kinds of mistakes
)that I make.  How many ADA programmers do you know of use LINT?

Ada programmers don't use lint, they don't have to.

From another article by Scott MacHaffie:
)Good programmers understand the language they are using -- good programmers
)are literate. No language can eliminate errors. Good software engineering
)practices should be used to (try to) catch language-specific errors.

And good languages should have as few unnecessary traps as possible
to help the software engineer spend his efforts on essentials.
-- 
Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (02/25/90)

From peter@ficc.uu.net (Peter da Silva):
> On the other hand, the people (inlcuding Bill) arguing that switch...break
> is an unalloyed disaster are also all wet.  The C SWITCH is not a Pascal
> CASE, it's a computed goto:   [Fallthrough example]

   Which, amazingly enough, I explicitly noted in my original article:

     [...] In C, the case statement *requires* the
     use of a restricted GOTO in order to accomplish "normal" processing;
     at the end of the section of code processing a given case, one must
     use a restricted GOTO in order to prevent C from sending the flow of
     control straight into the section of code which was intended to process
     the NEXT case.  In other words, C requires the programmer to use a
     dangerous construct on a routine basis.

   Many (including Peter) have re-observed that this is the way C's switch
   currently operates, but to date nobody has provided any justification for
   having it continue to operate that way.  Apparently the thinking is that
   if the current definition is repeated often enough, it will be accepted
   regardless of how completely bizarre it is.  

   Given the fact that switch..break results in the generation of many
   unnecessary lines of "break" code, that it requires its users to get 
   into the habit of using a restricted GOTO to accomplish "normal" 
   processing (the expensive nature of this habit being dramatically 
   demonstrated by the recent nationwide AT&T crash), and that there 
   is a widely used (and considerably safer) alternative, it would seem 
   that C would be considerably better off if it were to either redefine 
   or replace its switch construct with a case statement.


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

   P.S.  Pending this change, feel free to use Ada instead...  :^) 

karl@haddock.ima.isc.com (Karl Heuer) (02/26/90)

In article <4611@jarthur.Claremont.EDU> jseidman@jarthur.Claremont.EDU (James Seidman) writes:
>[Because of a problem with accidentally writing `foo:' for `case foo:', where
>`foo' is an identifier denoting an enum constant,] Labeled statements inside
>a case statement would be a nice addition to lint

Unnecessary.  Each of SysV lint, BSD lint, and gcc -Wall will already issue at
least one warning for this.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

woody@rpp386.cactus.org (Woodrow Baker) (02/26/90)

In article <2905@goanna.oz.au>, ok@goanna.oz.au (Richard O'keefe) writes:
> : This argument seems to me about equivalent to saying "One
> : of the debatable features about 'if' is that a new program block is not
> : defined.  That means that you can have a statement which you meant to have
> : in the if statement but isn't."  You know, something like
> :   if (a == b)
> : 	bar(a);
> : 	foo(a);
> :   a++;
> : Do you propose making an editor macro to handle ifs to prevent this?

No:  Fix the compiler to require curly braces around ALL elements of control
structures, whether they are 1 line or not.

> 		case...
> 		    ...
> 			/* now I want to exit the LOOP */
> 				
> (a) can't be done without introducing a goto or return, or rewriting
>     the code.
Wrong.  you can always set a flag within the various cases and test it at
the bottom or top of the loop.  Yes this qualifies as re-writing the code.
But you don't have to use **goto**  (shudder)
Personaly, I feel that curly braces around BOTH parts of if...else...
constructs, and around, while loops, do whiles...case and switch statements
and break statements in cases should be mandantory and enforced as syntax
errors by the compiler if not done.  'C' is just super flexible, but who
needs 6 ways of finding the address of the first element of an array?

Cheers
Woody

woody@rpp386.cactus.org (Woodrow Baker) (02/26/90)

In article <SUY1G_Fxds13@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes:
> 	switch(c)
> 	{
> 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
> 			digit();
> 		default:
> 			not_a_digit();
> 	}
> 
I'd fire a programmer for code like this:

> a loop. I would suggest that 'break' be given a mandatory keyword argument:
> either 'break switch', 'break for', and so on.

So go define a macro to do that.

#define break_switch  break

Cheers
Woody

peter@ficc.uu.net (Peter da Silva) (02/26/90)

First of all, my point about gotos had nothing to do with your point
about gotos.

In article <8145@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>    Many (including Peter) have re-observed that this is the way C's switch
>    currently operates, but to date nobody has provided any justification for
>    having it continue to operate that way.

I'm not going to bother continuing this discussion. The very article you were
referencing shows an example of how the C switch construct may be profitably
used. I can show you the working code I based that example on, if you like.
By all means make 'break' the default... but provide a convenient (not
involving explicit gotos) method of falling through to the next case.

The construct you seek has existed in C from the beginning:

#define CASE switch {
#define WHEN break; case
#define OR : case
#define DO :
#define OTHERWISE default:
#define ESAC }

	CASE (language)
		WHEN ADA OR COBOL DO
			blame the DOD;
		WHEN C OR FORTH DO
			blame people who wanted to get
			real work done instead of building
			more beauracracy;
		OTHERWISE
			see appropriate ANSI standards;
	ESAC
-- 
 _--_|\  Peter da Silva. +1 713 274 5180. <peter@ficc.uu.net>.
/      \
\_.--._/ Xenix Support -- it's not just a job, it's an adventure!
      v  "Have you hugged your wolf today?" `-_-'

misu_ss@uhura.cc.rochester.edu (What`s in a name?) (02/27/90)

In article <806@enea.se> sommar@enea.se (Erland Sommarskog) writes:
>Scott MacHaffie (machaffi@fred.cs.washington.edu.cs.washington.edu) writes:
>)Bill Wolfe (billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu) writes:
>))   the NEXT case.  In other words, C requires the programmer to use a
>))   dangerous construct on a routine basis.

>))	[stuff deleted]

>))   code associated with the else part.  Thus, we have an inconsistency
>))   in C's design: with one flow-of-control construct (the switch), it is
>))   necessary to use a dangerous GOTO to achieve normal processing, whereas
>)
>)No, it is necessary to use a statement to indicate that the current case
>)statement is finished...like an "end case" or the next "when =) " in ADA.
>
>I don't speak C, so I might have missunderstood something, but I'm
>under the impression that you may exclude the "break" statement
>achieving the effect that you execute the code for the next case too.
>Sometimes possibly a nifty feature, but it seems to me that is a good
>source of errors. Whether it's called "break" or "end case" has no
>importance. You may inadvertantly forget it in both cases.
>

Yupper.  To quote the Holy Scriptures:

"Falling through cases is a mixed blessing.  On the positive side, it allows
several cases to be attached to a single action... But it also implies that
normally each case must end with a break to prevent falling through to the
next.  Falling through from one case to another is not robust, being prone
to disintegration when the program is modified.  With the exception of
multiple labels for a single computation, fall-throughs should be used
sparingly and commented.
	"As a matter of good form, put a break after the last case even
thought it is logically unnecessary.  Some day when another case gets added
at the end, this bit of defensive programming will save you." (K&R p.59)

So, yes I'll agree this is a slight flaw in the case statement, but I'm not
sure I buy all this garbage about "break" being a "dangerous construct."

There has been a war on GOTO constructs for some time and while it certainly
began with reason (remember BASIC without labels???:-)), it gets to the
point where efficiency is not saved.  One really must go to great lengths to
program anything significant without some sort of flow control, which at the
machine level breaks down into conditional or unconditional jumping... (Yes,
a GOTO (EEEEEEKKKKK!!!!)).  

So, we want to be reasonable in our jumps, giving them certain well defined
conditions and having only certain types.  So we *do* indeed, for the most
part want to get rid of the monstrosity known as "GOTO label" (To say
nothing of the kind of line I could write in TRS-80 basic: 
    
     20 IF X OR 2 100 /* This jumps to line 100 if the 2 bit is set in X */
).

In fact I would argue that all GOTO like constructs should be conditional
and local.  And so they are (almost) in C.  For, while, switch, do... -- all
local, and all conditional except one:  break (Yeah, C has goto but everyone
knows never to use *that*).  But break is rather well defined in C.  It exits
from the innermost for, while, do or switch statement.  It goes to an easily
noticeable place near it in the code, unlike goto (let's go label hunting!).
Now I could argue that making the break statement conditional i.e. :

break(expression);  performs break if expression is true, nothing if false.

would be a good idea.  For one thing certain loop breaking would be easier
to write.  Admittedly the common uses in switch statements would require
three extra characters...  I don't think it's a big enough deal to be worth
changing.  Break simply isn't that dangerous.  I'm not so sure GOTO is all
that dangerous if treated with the proper respect (But then I've done
assembly programming...:-)). 

Arguments for the break statement:  Do you ever want to break out of a
while, for or do construct?  ("Oh, no!" I hear some say, "Properly written
programs *never* need do that."  My answer:  Yes, you are right and BTW,
every reasonable language is Turing Equivalent -- go program on a turing
machine.) The only option without some kind of break statement, is to use
flag variables and a couple of extra conditionals (Quoth my algorithms
professor, "Flag variables are as ugly as gotos, but they can't be helped in
Standard Pascal...").  

Thing is, lot's of things are pretty dangerous in programming languages but
these things can be very useful.  Noone in their right mind can claim that
pointer manipulation is any less dangerous than a flat out goto label
statement (IMNSHO, it's tremendously more dangerous), but would any
reasonable programmer trade it for the world?  There is simply too much that
becomes easy and elegant when you use pointers into real memory instead of
having to create your own integer index pointers into arrays simulating
memory in order to implement, say, a tree.  We did this in my algorithms
class, in order to learn about how pointers are implemented.  It's not that
hard, just painful and complicated.  I'll take pointers any day of the
week.  

I'm saying that we need not be quite so anal-retentive about the constructs
we allow in programming languages.  Admittedly, C is not for the faint of
heart, and I'll be surprised if it catches on in the big business world.
There is too much need for programming and not enough programmers who can
handle a C environment.  That's ok by me -- I'm really not interested in
that sort of dp anyway (although the poor saps ought to get something better
than C*BOL to use).  But the one thing that makes C more dangerous, more hairy,
more able to strike fear into the heart of the novice programmer than even
the demonic teenage Mike S. with his TRS-80 model III spaghetti basic
interpreter using Machine Language subroutines left and right, is C's use of
pointers and operators.  Not the silly break statement or some small
weakness in the switch.  

C pointers and operators, while hairy, are extremely elegant.  This is why
so many people like to program in C.  But admit it, they are not trivial to
understand.  So my main point is this:  

Anyone who has any business programming in C, should be able to handle a
switch statement where cases fall through.  

And it's true, every C programmer gets steeped in the heritage of the
switch.  Why the third commandment of C states quite clearly:

"Thou shalt put a break statement at the end of each case in a switch, even
unto the last in which it is not logically necessary."

So what's the problem?  If you feel so strongly about a switch statement
than you are obviously of a different school than C'ers.  

There are two main schools of looking at language implementation.  One,
typified by Standard Pascal, says that the programmer probably doesn't know
what s/he is doing and that a language should not let him/her do anything
even slightly out of the ordinary.  The second, typified by C, says that the
programmer knows or should know what s/he is doing and so "I'll just do what
s/he tells me as long as I understand what s/he is saying."  If you are a
type I programmer, using C must feel like walking a tightrope between the
towers of the world trade center.  If you are a type II programmer, using SP
is like trying to answer the four-year-old who has learned how to ask, "Why?"

The best languages are obviously not going to go whole hog in either
direction, but in general you should use what you feel comfortable with.  I
like C, You like Ada, so use what you like.  I think K&R made a reasonable
choice with break.  I like being able to fall through a switch, even if I
have to take a little care with it.  Do you think I type *anything* in C
without taking a certain amount of care?  

							--mike


-- 
Mic3hael Sullivan,                    Society for the Incurably Pompous
		     		-*-*-*-*- 
"In the usual way":  That's a phrase that mathematicians use to let you know
they're smarter than you are.				--Norman Stein

karl@haddock.ima.isc.com (Karl Heuer) (02/27/90)

I'm redirecting followups to comp.lang.misc.

In article <5479@ur-cc.UUCP> Michael Sullivan writes:
>[A lot of strawman arguments]

I don't think anybody is seriously arguing the position that you seem to be
attacking.  I also don't know how closely my position matches that of the
other participants in this debate, but I'll state mine as a series of claims
for you to agree with or rebut as you like.

It's meaningless to say "the `break' keyword is {good,bad}"; you have to have
an alternative to compare against.  I will use the notation `C with feature X'
to mean `a hypothetical language which is a lot like C but which has feature
X'; then we can make statements like `C with X would be a better tool than C'.

I am not arguing that C should be changed in this regard (except by adding
warning messages where appropriate).  Thus, the existence of a large body of
code written in C-as-it-is-today is not a factor in such comparisons.

We need to distinguish between keywords and the operations they denote.  It
turns out to be useful to distinguish two operations, which I will call
`break-switch' and `break-loop', both of which are denoted by the keyword
`break' (depending on context).  I will use the term `fall-through' to denote
the operation of flowing from the end of one case into the beginning of the
next one; this operation is denoted in C by the absence of a `break' keyword
in reachable flow at the end of a case block.

Claim 0.  Much use of fall-through in C is simply attaching several cases to a
single action.  (In fact, this is the `positive side' you quoted from the Holy
Scriptures.)  Some other languages achieve this by allowing multiple values to
be associated with a single case label, instead.  Thus, C with multiple valued
cases would not need fall-through nearly as often.

Claim 1.  A break-switch is rarely needed at any point other than at the end
of a case block.  At the end of a case block, break-switch is needed much more
often than fall-through.

Claim 2.  As a general principle, if there is a default action it should be
the most common of the alternatives.  This tends to minimize certain kinds of
user errors.

Definitions.  Let `CX' be the language C with multiple valued cases, with
automatic break-switch at the end of each case block, and with the `break'
keyword denoting only the break-loop operation.  `CX with jumpcase' is CX
with an explicit keyword to denote the fall-through operations (overriding the
default behavior of an automatic break-switch).

Claim 3.  CX with jumpcase would be better than C.

Claim 4.  CX itself would be better than CX with jumpcase (and hence better
than C); the extra keyword doesn't buy you enough to be worth adding, and it
would destroy the commutativity of case blocks, which is a useful property of
CX.

Claim 5.  Because C, not CX, is what we actually have, and because of what I
said in Claim 1, a useful feature of C compilers and/or checkers (lint) is the
ability to produce a warning if (a) a `break' keyword denoting a break-switch
operation appears anywhere other than at the end of a case block, or (b) a
(reachable) fall-through operation occurs at the end of a case block.

Claim 6.  In the case of lint, at least, such warnings should be enabled by
default.  There should be lintpragmas (e.g. /*SWITCH*/, /*FALLTHROUGH*/) that
can selectively disable them.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

chittamu@umvlsi.ecs.umass.edu (Satish Kumar .C) (02/27/90)

In article <10839@june.cs.washington.edu> machaffi@fred.cs.washington.edu.cs.washington.edu (Scott MacHaffie) writes:
>In article <8133@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
>>   common practice to use break statements by the dozen in order to get 

>switch (x) {
>	case '0': case '1': ... case '9':
>		digit(x);
>		break;
>}
>
>ADA-C:
>switch (x) {
>	case '0': digit(x);
>	case '1': digit(x);
>	...
>	case '9': digit(x);
>}
>		Scott MacHaffie

Give me a break. In Ada, you would actually write it as

case x 
 when '0' | '1' | '2' =>
     digit(x) ;
end case;

I am sure one can come up with a reasonable syntax for the equivalent
in "Ada-C".

No personal offense intended, but if the only argument you have for
C needing breaks on a case is that you need to write only one action,
then all I can say is it is positively absurd.

-- 
	-Satish.
	chittamu@cs.umass.edu
--
The Theory of Objectivity: E = MC++

dougcc@csv.viccol.edu.au (Douglas Miller) (02/27/90)

In article <4174@ganymede.inmos.co.uk>, mph@lion.inmos.co.uk (Mike Harrison) writes:
> In article <5017@csv.viccol.edu.au> dougcc@csv.viccol.edu.au (Douglas Miller) writes:
>>Valid but utterly vacuous point, as ADA *was* designed to provide maximal
>>support for software engineering.  I suppose its possible that another
>>(hidden?) design goal was to "have everything".  So what?
>>
> Wrong ! - Ada was designed primarily to save DoD money, secondarily to support
> very long in-service life software (by simplifying the maintenance process), 
> with all kinds of other goodies as a tertiary aim.

I know, these were the *requirements*.  ADA was *designed* to meet these
requirements by providing maximal support for software engineering.

Alternatively I could argue that the requirements you mention basically
define what software engineering is, and you are just nitpicking.

ok@goanna.oz.au (Richard O'keefe) (02/27/90)

In article <18033@rpp386.cactus.org>, woody@rpp386.cactus.org (Woodrow Baker) writes:
> In article <2905@goanna.oz.au>, ok@goanna.oz.au (Richard O'keefe) writes:

In fact the section which follows was QUOTED by me, not WRITTEN by me.
Please net.people, do take care with your attributions.

I _did_ write
> > (a) can't be done without introducing a goto or return, or rewriting
> >     the code.
to which Woodrow Baker responded
> Wrong.  you can always set a flag within the various cases and test it at
> the bottom or top of the loop.  Yes this qualifies as re-writing the code.

It seems very odd to say "Wrong" and then admit two sentences later that
it isn't wrong at all.  Look, you can program _any_ can of spaghetti you
like with _one_ loop, _one_ switch, and _one_ flag variable.  The goal is
code that can be read and understood without too much strain; post hoc
flag variables are even worse for that than undisguised gotos.

In Ada, the method of quitting a loop early is the exit statement:
	<Ada LRM 5.7 para 2>
	exit_statement ::= EXIT [loop_name] [WHEN condition];
With no loop_name, it exits the innermost loop.
With a loop_name, it exits the loop labelled with that loop_name.
An equivalent for C would be a set of macros like

	loop(LoopName)
	    break_loop(LoopName)
	end_loop(LoopName)

which could be implemented thus:

	#define loop(X) {
	#define break_loop(X) goto X
	#define end_loop(X) ;X:;}

This does amount to bending the syntax of C, but I think it may be an
excusable case.  The proper nesting of these macros can be easily checked
by a simple tool, and it gives us a disciplined way of using the language
we already have.

msb@sq.sq.com (Mark Brader) (02/28/90)

Dick Dunn writes in comp.lang.postscript:
|  Look, this isn't alt.flame.  Some of us read this group to exchange ideas
|  about PostScript, not to watch all the wannabes preen their egos and whine
|  about what is, in the final analysis, the fact that Adobe created
|  PostScript and they didn't.
|  
|  If there's any of the "Love it or leave it" philosophy here, it's in the
|  anti-Adobe attitude that seems to say that Adobe is evil because they're
|  successful, and that anyone who isn't flaming Adobe must be a simpering
|  sycophant.  Anyone who dares to be *happy* about PostScript, or who finds
|  it *incredibly useful*, is somehow on the defensive lately.

If he had said "C" instead of "PostScript" and "Adobe", much of this
would be equally applicable to certain recent traffic in this newsgroup.

-- 
Mark Brader		"Not looking like Pascal is not a language deficiency!"
utzoo!sq!msb, msb@sq.com					  -- Doug Gwyn

Dennis.Schmitz@f1505.n106.z1.fidonet.org (Dennis Schmitz) (03/01/90)

In an article of <23 Feb 90 03:17:30 GMT>, ok@goanna.oz.au (Richard O'keefe) writes:

 RO>and exiting from a loop.  I've lost count of the number of times I have
 RO>had to add a label, use a 'return', or restructure my program simply
 RO>because the place where I wanted to put a loop 'break' was inside a
 RO>switch.  The real pity of it is that BCPL used two different keywords

From 'Microsoft C Language Reference' p.152,
=============
6.2 the break statement

break;

* execution

The break statement terminates the execution of the smallest enclosing do, 
for, switch, or while statement in chich it appears....
=============

So, why would you have to restructure your program?

Later,
dEN

tombre@crin.fr (Karl Tombre) (03/01/90)

In article <259@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
   From <Ec.3251@cs.psu.edu> by melling@cs.psu.edu (Michael D Mellinger):

   > Personally, it's the little things like this that make me
   > believe that everyone should ABANDON C and move on to C++(two others being
   > function prototyping and strong type checking).  Waddya think?  Wither C?

       How can the words ``strong type checking'' be applied to a language
   in which any variable may be cast to any type? In which you declare the
   type of a generic list element to be ``pointer to characters''?

       C++ only magnifies the problems of C, and it does not even have the
   excuses that can be invoked in the case of a 20-year old design such as C.
   [and so on]

Am I the only one having regularly the following problem?

I think Eiffel is a very good language (probably one of the best), I
am quite impressed by its design. I also appreciate Bertrand Meyer's
various technical and scientifical contributions in conferences and
newsgroups. But from time to time, this attitude of his comes up and
annoys me VERY MUCH : he seems to have difficulties accepting that
there are other solutions for object-oriented programming, that other
languages exist and are popular for various reasons. He especially
tends to become "rabid" when speaking of C++. This leaves such a bad
"taste in my mouth" that it tends to give me unjustly biased views of
Mr. Meyer's product, i.e. Eiffel.

That any "neutral" user gives his opinion about the merits or
deficiencies of C++, Eiffel, Smalltalk, Cobol, BASIC or whatever is
just fine. But shouldn't it be plain decency to restrain from
commenting in such strong and passionnate terms about one's
concurrents' products ? Especially for somebody wishing not to be
a marketing person but to be known as an authority in OO languages and
design ? I remember for instance reading some time ago, in the news,
comments from either Brad Cox or Bjarne Stroustrup about the other's
language; at no time did it have such a bad taste than the referenced
article. Isn't it on the border of arrogance to believe that "I know
the definite, final and only TRUTH about how an object-oriented
language should be designed" ???

--
Karl Tombre - INRIA Lorraine / CRIN
EMAIL : tombre@loria.crin.fr - POST : BP 239, 54506 VANDOEUVRE CEDEX, France

bertrand@eiffel.UUCP (Bertrand Meyer) (03/01/90)

From <Ec.3251@cs.psu.edu> by melling@cs.psu.edu (Michael D Mellinger):

> Personally, it's the little things like this that make me
> believe that everyone should ABANDON C and move on to C++(two others being
> function prototyping and strong type checking).  Waddya think?  Wither C?


    How can the words ``strong type checking'' be applied to a language
in which any variable may be cast to any type? In which you declare the
type of a generic list element to be ``pointer to characters''?

    C++ only magnifies the problems of C, and it does not even have the
excuses that can be invoked in the case of a 20-year old design such as C.
All the flaws of the older language are still there; amount countless
examples, the break and switch instructions, which were purportedly
responsible for the AT&T breakdown (and started this whole discussion)
are still there exactly as in C. The bug would have occurred identically.

    Then there are new complexities and major new trouble spots -
such as default static binding, which means the guarantee that the
*incorrect* version of an operation will be applied!

-- Bertrand Meyer
bertrand@eiffel.com

henry@utzoo.uucp (Henry Spencer) (03/02/90)

In article <259@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>> Personally, it's the little things like this that make me
>> believe that everyone should ABANDON C and move on to C++(two others being
>> function prototyping and strong type checking)...
>
>    How can the words ``strong type checking'' be applied to a language
>in which any variable may be cast to any type? In which you declare the
>type of a generic list element to be ``pointer to characters''?

Come now, at least criticize the modern language, not a caricature of
what you think it was fifteen years ago.  Many "systems programming"
languages allow deliberate unsafe type conversions if you request them,
and they are not considered any less "strongly typed" for it.  Modern
C is a strongly-typed language by any reasonable definition, although
there are still a lot of antique compilers around that don't fully
enforce its rules.  (NB you can't cast any variable to any type in C,
only certain combinations are valid.)  And any modern generic pointer
declaration will say `void *' not `char *'.

There are enough real problems with C and C++ without making up silly
strawmen.

(P.S. They remain eminently usable languages for people who know what
they're doing, although incompetents and novices should definitely
avoid them.  Alas, all too many of the "real programs" in the world are
written by incompetents and novices...)
-- 
MSDOS, abbrev:  Maybe SomeDay |     Henry Spencer at U of Toronto Zoology
an Operating System.          | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

sommar@enea.se (Erland Sommarskog) (03/02/90)

Michael Sullivan (misu_ss@uhura.cc.rochester.edu) writes:
>"Thou shalt put a break statement at the end of each case in a switch, even
>unto the last in which it is not logically necessary."
>
>So what's the problem?

The problem? Such rules such be enforced by the compiler, not the
programmer. The more rules you into a language which the programmer
is to obey without the compiler to verify, the more likely it is
that casual errors slip in. And the compiler checks for me, the more
I can concentrate on the essentials; trying to solve the real-world
problem at hand.
-- 
Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se

nick@lfcs.ed.ac.uk (Nick Rothwell) (03/02/90)

In article <1990Mar1.172526.28683@utzoo.uucp>, henry@utzoo (Henry Spencer) writes:
>Modern
>C is a strongly-typed language by any reasonable definition,

Could you give me a reference to the type semantics?

		Nick.
Nick Rothwell,	Laboratory for Foundations of Computer Science, Edinburgh.
		nick@lfcs.ed.ac.uk    <Atlantic Ocean>!mcvax!ukc!lfcs!nick
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
      A prop?   ...or wings?      A prop?   ...or wings?      A prop?

feg@clyde.ATT.COM (Forrest Gehrke,2C-119,7239,ATTBL) (03/02/90)

In article <1990Mar1.172526.28683@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> 
> There are enough real problems with C and C++ without making up silly
> strawmen.
> 
> (P.S. They remain eminently usable languages for people who know what
> they're doing, although incompetents and novices should definitely
> avoid them.  Alas, all too many of the "real programs" in the world are
> written by incompetents and novices...)



While I agree 100% with everything you said in this article in
support of the modern C language, aren't you being a little
contradictory in your postscript?  Unless you anticipated
Dennis Ritchie, one day you too were a novice in C.  Fortunately
you didn't avoid it.  (;-))

Forrest Gehrke feg@clyde.ATT.COM

karl@haddock.ima.isc.com (Karl Heuer) (03/03/90)

In article <1004@micropen> dave@micropen (David F. Carlson) writes:
>What break does is *very* well defined and is no more prone to
>misinterpretation that any other non-linear control flow statement ...

Yes, it's well defined, but what it's defined to do is bad.

For a formal treatment of the above statement, I refer you to my article
<16039@haddock.ima.isc.com>, posted to comp.lang.misc (also .c and .ada) with
this same title.  I haven't seen any rebuttals yet.

>A multi-case switch is very handy in many situations ...

Yeah.  I wish C had this feature, instead of simulating it with fallthrough.

>That you ask the question of the usefulness of break-per-case/multiple-cases
>implies that you haven't sufficient experience with the construct to judge
>its merits/weaknesses.

I don't know about the person you were addressing, but I think I've had
sufficient experience with it.  I certainly question its usefulness in
comparison to something reasonable, like the language I described in my other
article.

In fact, even if you insist that the comparison must be between C and
plain-C-without-break-switch, I think I'd still go for the latter.  I believe
the benefit of not requiring an overloaded keyword to do a break-switch
exceeds the cost of having to use a goto to merge related cases.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

dan@charyb.COM (Dan Mick) (03/03/90)

In article <TOMBRE.90Mar1013132@weissenburger.crin.fr| tombre@crin.fr (Karl Tombre) writes:
|In article <259@eiffel.UUCP| bertrand@eiffel.UUCP (Bertrand Meyer) writes:
|   From <Ec.3251@cs.psu.edu| by melling@cs.psu.edu (Michael D Mellinger):
|
|   | Personally, it's the little things like this that make me
|   | believe that everyone should ABANDON C and move on to C++(two others being
|   | function prototyping and strong type checking).  Waddya think?  Wither C?
|
|       How can the words ``strong type checking'' be applied to a language
|   in which any variable may be cast to any type? In which you declare the
|   type of a generic list element to be ``pointer to characters''?
|
|       C++ only magnifies the problems of C, and it does not even have the
|   excuses that can be invoked in the case of a 20-year old design such as C.
|   [and so on]
|
|Am I the only one having regularly the following problem?

No.

|I think Eiffel is a very good language (probably one of the best), I
|am quite impressed by its design. I also appreciate Bertrand Meyer's
|various technical and scientifical contributions in conferences and
|newsgroups. But from time to time, this attitude of his comes up and
|annoys me VERY MUCH : he seems to have difficulties accepting that
|there are other solutions for object-oriented programming, that other
|languages exist and are popular for various reasons. He especially
|tends to become "rabid" when speaking of C++. This leaves such a bad
|"taste in my mouth" that it tends to give me unjustly biased views of
|Mr. Meyer's product, i.e. Eiffel.

I know nothing *at all* about Eiffel, and I'm much less encouraged to learn
about it based on Bertrand's comments.  It's not that I'm less interested
in it technically; it's just that, due to his attitude toward communication in
general, I'm less apt to believe anything he's done technically is useful.

|That any "neutral" user gives his opinion about the merits or
|deficiencies of C++, Eiffel, Smalltalk, Cobol, BASIC or whatever is
|just fine. But shouldn't it be plain decency to restrain from
|commenting in such strong and passionnate terms about one's
|concurrents' products ? Especially for somebody wishing not to be
|a marketing person but to be known as an authority in OO languages and
|design ? I remember for instance reading some time ago, in the news,
|comments from either Brad Cox or Bjarne Stroustrup about the other's
|language; at no time did it have such a bad taste than the referenced
|article. Isn't it on the border of arrogance to believe that "I know
|the definite, final and only TRUTH about how an object-oriented
|language should be designed" ???

Yes.   Yes, it should. 



Unfortunately, the world is run by sales slime.  Good luck telling the
difference.

henry@utzoo.uucp (Henry Spencer) (03/03/90)

In article <2568@castle.ed.ac.uk> nick@lfcs.ed.ac.uk (Nick Rothwell) writes:
>>Modern
>>C is a strongly-typed language by any reasonable definition,
>
>Could you give me a reference to the type semantics?

ANSI X3.159 (I think that's the correct number) defines all the semantics
of C.  Publication is imminent.

"Strongly typed" and "has a mathematically formal definition of type
semantics" are two entirely different concepts, in case the latter was
what you were thinking of.  As far as I know, nobody has yet produced
a formal definition of C.  It is possible, although painful, to formally
define non-strongly-typed languages.
-- 
MSDOS, abbrev:  Maybe SomeDay |     Henry Spencer at U of Toronto Zoology
an Operating System.          | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

henry@utzoo.uucp (Henry Spencer) (03/04/90)

In article <4397@cbnewsl.ATT.COM> feg@clyde.ATT.COM writes:
>> ([C/C++] remain eminently usable languages for people who know what
>> they're doing, although incompetents and novices should definitely
>> avoid them.  Alas, all too many of the "real programs" in the world are
>> written by incompetents and novices...)
>
>While I agree 100% with everything you said in this article in
>support of the modern C language, aren't you being a little
>contradictory in your postscript?  Unless you anticipated
>Dennis Ritchie, one day you too were a novice in C.  Fortunately
>you didn't avoid it.  (;-))

I should have drawn slightly finer distinctions here.  Programming novices
should avoid C, period.  Experienced programmers who are C novices should
use C cautiously and avoid using it for production software, if possible,
until they're used to it.  Incompetents should go somewhere where their
lack of talent will not be noticed, e.g. the local DoD contractor. :-)
(It's no accident that one big push for languages that try to legislate
competence comes from DoD...)

Yeah, I was a C novice once.  I'm glad that all the code I wrote then
is dead and buried.
-- 
MSDOS, abbrev:  Maybe SomeDay |     Henry Spencer at U of Toronto Zoology
an Operating System.          | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bph@buengc.BU.EDU (Blair P. Houghton) (03/04/90)

In article <V4-1JQExds13@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>First of all, my point about gotos had nothing to do with your point
>about gotos.
>
>In article <8145@hubcap.clemson.edu> billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu writes:
[Three lines]

>I'm not going to bother continuing this discussion.
[Thirty lines]

Glad you didn't bother.

				--Blair
				  "All I can think of is the 'h' word."

g2k@mentor.cc.purdue.edu (Frederic Giacometti) (03/05/90)

In article <TOMBRE.90Mar1013132@weissenburger.crin.fr> tombre@crin.fr (Karl Tombre) writes:
>In article <259@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>   From <Ec.3251@cs.psu.edu> by melling@cs.psu.edu (Michael D Mellinger):
>
>   > Personally, it's the little things like this that make me
>   > believe that everyone should ABANDON C and move on to C++(two others being
>   > function prototyping and strong type checking).  Waddya think?  Wither C?
>
>       How can the words ``strong type checking'' be applied to a language
>   in which any variable may be cast to any type? In which you declare the
>   type of a generic list element to be ``pointer to characters''?
>
>       C++ only magnifies the problems of C, and it does not even have the
>   excuses that can be invoked in the case of a 20-year old design such as C.
>   [and so on]
>
>Am I the only one having regularly the following problem?
>
 ..........
>article. Isn't it on the border of arrogance to believe that "I know
>the definite, final and only TRUTH about how an object-oriented
>language should be designed" ???
>


  Firstly, let me clear up my position on the C/C++ problem: I agree
completely with B. Meyer on C/C++. Is it being arrogant than saying
that C++ is no more than a bricolage around C when it is the mere truth ?
  B. Meyer, may strongly cast his opinions, sometimes subtility is the mark
of a good mind, but there are other
marks as much valuable, among which are frankness and clarity of one's
opinion. 

  Secondly, a cultural problem has to be addressed. I am surprised to see this article emitted from a site in France; that
person should know that "every frenchman is arrogant" (one of the most
common image of French in america: lover and arrogant). This net is not the
place to discuss these features of French culture and education which
make that Frecnh intellectual life is particularly animated and opiniated (a feature one also
finds in Quebeccan politics), a severe contrast with the blendness of anglo-saxon puritan life.
By looking at his first name, I shall consider that Karl must not be french.
  
  Thirdly, I admire the courage of B. Meyer who successfully started his
own independent business. What he is doing is unique in the annals of
computer science: to center the development of a new company around the
development of a language. And I assert that it is a certificate of
quality about the language. As example of low techinical quality products
which were commercially successfull because of a name, one can quote the
IBM PC line.
  If you look at the history of computer science,
major developments (Apple is the exception) have usually been produced
by major corporations rather than by motivated individuals. This dynamism
derives from a strong personality (another arrogant man of which we
recently heard of was Steve Jobs with his NeXT machines). At least
B. Meyer engages the discussion and takes position on problems, whatever
it be. He does not hide himself beyond some obscur corporate barrier. 
Discussions on the net are technical, not commercial. Meyer exposes his
technical point of view, not more. Until now, I haven't seen many flaws in his
analyzes; if so let me know. His position has the merit of the clarity. 
One only has to know it.

  So far, C++ has taken up not much because of its intrinsic value, but
because of the support of AT&T. Besides the problems specific to C, it is
not even a complete object-oriented language (where is the dynamic binding ?).
The compatibility with C is more or less its only advantage from a technical
point of view. When he designed the language, Stroustrup grabbed some
ideas from Modula, and put some inheritance paradigm. On top of that,
the american press, hearing the name AT&T, rushed into it. Bof, it may
convince the one who like to follow the masses.  In that case, it is sure
that the voice of Meyer is very unpleasant, it disturbes what one wants
to hear: the mass is right and secure.

 I maintain that, although for programmers who know C, C++ is the seducing
solution, C++ has exceedingly weak theoretical bases to justify its use
in the future. Should this be considered as arrogance ?
  Eiffel has a very strong theoretical and formal support. It is the
product of a rigorous approach. All the contrary of C++, of which approach is
pragmatic, aimed at solving a short term industrial problem: how to improve
C without throwing it away. Well, it is with such raisonning that america
is still using the english system of measures, and other degree Farenheit,
to the great pleasure of the future generations and technological progress
of america.

Frederic Giacometti
School of Industrial Engineering
Purdue University

tat@pccuts.pcc.amdahl.com (Tom Thackrey) (03/06/90)

In article <1990Mar4.005122.14121@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
 >I should have drawn slightly finer distinctions here.  Programming novices
 >should avoid C, period.  Experienced programmers who are C novices should
 >use C cautiously and avoid using it for production software, if possible,
 >until they're used to it.  Incompetents should go somewhere where their
 >lack of talent will not be noticed, e.g. the local DoD contractor. :-)
 >(It's no accident that one big push for languages that try to legislate
 >competence comes from DoD...)
Why is it necessary to slander some group or another to make a point?
BTW If they didn't notice why would they push ...?

-- 
Tom Thackrey sun!amdahl!tat00

[ The opinions expressed herin are mine alone. ]

harrison@necssd.NEC.COM (Mark Harrison) (03/06/90)

In article <2905@goanna.oz.au>, ok@goanna.oz.au (Richard O'keefe) writes:

> : defined.  That means that you can have a statement which you meant to have
> : in the if statement but isn't."  You know, something like
> :   if (a == b)
> :        bar(a);
> :        foo(a);
> :   a++;
> : Do you propose making an editor macro to handle ifs to prevent this?

You might look at Gimpel Software's PC-Lint and Flexe-Lint packages.  It will
warn you if your indenting does not match your curly braces, along with
dozens of other really useful warnings (printf args not matching fmt string,
etc.)

They advertise in Dr. Dobbs, Comp. Language, etc.  The two programs are the
same; PC-Lint runs on MS-DOS, Flexe-lint runs on Unix, VMS, CMS, Amiga,
Macintosh, and just about any other environment that supports K&R C.
-- 
------------------------------------------------------------------------
Mark Harrison				| (these opinions
harrison@necssd.NEC.COM			|  are my own, etc.)
{necntc, cs.utexas.edu}!necssd!harrison |

andrewt@watnow.waterloo.edu (Andrew Thomas) (03/07/90)

In article x karl@haddock.ima.isc.com (Karl Heuer) writes:

> Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

I'm sorry to hear that.  Perhaps you should clean your drier filter? :-)

--

Andrew Thomas
andrewt@watsnew.waterloo.edu	Systems Design Eng.	University of Waterloo
"If a million people do a stupid thing, it's still a stupid thing." - Opus

scm@dlcq15.datlog.co.uk (Steve Mawer) (03/07/90)

In article <669@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>
>Finally I would like to add another experience with switch:
>Some day, I had written the following piece of code:
>	switch (x = getsound()) {
>	DING:	/*stuff*/
>		break;	<----- No, *this* was not missing
>	}
>Do you see, what is wrong with that?
>I did not write "case DING:" aso., so DING: was considered to be a
>goto-label (and as such had a different name space as enum names and
>the program compiled without errors).

Yeah, I saw someone spend *ages* finding out why his default case never
got executed.  Turned out he'd spelt it `defualt'.
-- 
Steve C. Mawer        <scm@datlog.co.uk> or < {backbone}!ukc!datlog!scm >
                       Voice:  +44 1 863 0383 (x2153)

jharkins@sagpd1.UUCP (Jim Harkins) (03/08/90)

In article <2905@goanna.oz.au>, ok@goanna.oz.au (Richard O'keefe) writes:
> : defined.  That means that you can have a statement which you meant to have
> : in the if statement but isn't."  You know, something like
> :   if (a == b)
> :        bar(a);
> :        foo(a);
> :   a++;
> : Do you propose making an editor macro to handle ifs to prevent this?

How do you know he didn't really mean

	if (a == b)
		bar(a);
	foo(a);
	a++;

Of course, the a++ is probably a dead givaway but in the real world the 
examples are seldom so.  Basically, you either have a programming error
(solution: install brackets) or a stylistic error (solution: delete the
unwanted tab).  I for one like the flexibility to format my code the way
I like it, if I do something stupid and the code doesn't work as expected
it's my fault, not the language's.


-- 
jim		jharkins@sagpd1

"My hope is that we can use tariffs to force Japan to open their markets to
 imported goods.  My fear is I'll be forced to buy lousy American made stuff."

schow@bcarh185.bnr.ca (Stanley T.H. Chow) (03/09/90)

In article <TOMBRE.90Mar1013132@weissenburger.crin.fr> tombre@crin.fr (Karl Tombre) writes:
>In article <259@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>   From <Ec.3251@cs.psu.edu> by melling@cs.psu.edu (Michael D Mellinger):
>
>   > Personally, it's the little things like this that make me
>   > believe that everyone should ABANDON C and move on to C++(two others being
>   > function prototyping and strong type checking).  Waddya think?  Wither C?
>
>       How can the words ``strong type checking'' be applied to a language
			    ^^^^^^^^^^^^^^^^^^^^
>   in which any variable may be cast to any type? In which you declare the
>   type of a generic list element to be ``pointer to characters''?
>
>       C++ only magnifies the problems of C, and it does not even have the
>   excuses that can be invoked in the case of a 20-year old design such as C.
>   [and so on]
>
>Am I the only one having regularly the following problem?
>
> [...]      But from time to time, this attitude of his comes up and
>annoys me VERY MUCH : he seems to have difficulties accepting that
>there are other solutions for object-oriented programming, that other
			       ^^^^^^^^^^^^^^^
>languages exist and are popular for various reasons. He especially
>tends to become "rabid" when speaking of C++.  [...]

Perhaps you ought to *read* what you quote. It seems to me *you* are 
the one with the attitude problem.

Mr. Meyer stated one explicite objection - that C++ cannot be said to have
'strong type checking'. He also stated one general observation - that
C++ magnifies the problems of C. He made no comments regarding any of
the object-oriented features.

Since the thread is about the "robustness" of languages, and Mr. 
Mellinger suggested C++ for its strong type checking, I think it is
entirely fair for Mr. Meyer to comment on this topic.

If you disagree with Mr. Meyer, feel free to post why you think C++
does have strong type checking.

Stanley Chow        BitNet:  schow@BNR.CA
BNR		    UUCP:    ..!psuvax1!BNR.CA.bitnet!schow
(613) 763-2831		     ..!utgpu!bnr-vpa!bnr-rsc!schow%bcarh185
Me? Represent other people? Don't make them laugh so hard.

jimad@microsoft.UUCP (Jim ADCOCK) (03/09/90)

In article <259@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:

[Not totally without cause, IMHO]

>    How can the words ``strong type checking'' be applied to a language
>in which any variable may be cast to any type? 

How can the words 'strong type checking' be applied to a language that
gets its permissions on return types exactly backasswards?  Fix your
*own* language, before throwing stones, Bertrand!

In C++ not any variable can be cast to any type, although many questionable
casts are allowed *if specifically called for by the programmer*

In this light C++ follows the C lead of assuming the programmer is a mature
adult who can make his/her own decisions on these things.  Other languages
don't *really* prohibit programmers from doing these things where the programmer
desires -- if worse comes to worse, the programmer just breaks out the
old assembly language, and does what is necessary to get the job done.

A problem C++ has is that the C++ community has a large number of old
C hackers who run fast and loose with their coercions, and then find
that in C++ these hacks tend to bite them.  But, at least C++ *has*
this large community of old C hackers.  [Not to use the term "hacker"
in a totally derogatory sense]

The biggest problem [IMHO] is the continued heavy dependence by
many C++ programmers/implementations on the C Pre Processor --
which allows for textual substitutions to text code before the code
even gets to the C++ compiler.  Not only is the C Pre Processor
totally *not* type safe, it also allows programmer to make all kinds
of hacks to the [apparent] syntax of their code.  Further, the C Pre-
Processor makes simple tasks, such as the correct importing/exporting
of definitions a real nuisance.

>In which you declare the type of a generic list element to be 
>``pointer to characters''?

C++ provides "C" primitives like "pointer to char" that programmers can
use to create their own well encapsulated higher-level classes such
as "String."  Other OOPL languages, such as Eiffel, do not provide
this low level support.  Instead, the authors of these other languages
break out their handy-dandy "C" compiler and program up *one*
version of a "String" class that *all* users of the language must use --
even if it doesn't make the optimal speed/space/complexity tradeoffs
for that a particular user needs.  This heavy dependence on standard
libraries to do everything tends to mean that OOPLs taking this approach
only come from one vendor.  Better to provide compilers and libraries
separately, and allow users to choose which from where best meet their
needs.

C++ attempts to provide the power and flexibility to cover the entire
spectrum of programming tasks users need to do.  This includes the
power and flexibility to hose yourself, if you insist on doing so.

>    C++ only magnifies the problems of C, and it does not even have the
>excuses that can be invoked in the case of a 20-year old design such as C.

I am somewhat sympathetic to this complaint.  The latest definitions of
C++ try to be backwardly compatible with K&R C, ANSI-C, and previous
versions of C++.  In some areas, this makes for some pretty complicated
language rules.  This makes the life of compiler writers harder, so that
users can write C/C++ code as they are use to writing, and most of the
time their software will compile without compiler squawks.  Personally,
I think it would be good to give up some of the backward compatibility
in order to clean up some of the language rules.  Perhaps this will
happen as part of the ANSI-C++ standardization effort.  In any case, it
will be nice to have a standardize OOP language.

>All the flaws of the older language are still there; amount countless
>examples, the break and switch instructions, which were purportedly
>responsible for the AT&T breakdown (and started this whole discussion)
>are still there exactly as in C. The bug would have occurred identically.

C++ OOP programmers avoid switch statements as not being "object oriented,"
so propagating this "C" bogosity to C++ is not much of a problem.  Compilers
can choose to warn against missing break statement, if the compiler writers
so choose.  Better yet, an OOPL compiler should warn against using
switch statements in the first place!  

>    Then there are new complexities and major new trouble spots -
>such as default static binding, which means the guarantee that the
>*incorrect* version of an operation will be applied!

I disagree.  If a programmer wants a member function to answer to a
particular abstract protocol, the programmer creates such an abstract
protocol, marking its member functions "virtual", and inherits the
protocol in concrete classes matching that protocol.  Member functions 
in those concrete classes that match the abstract protocol are 
automatically default dynamic binding.  The "default static binding" 
you mention keeps classes with method names that *accidentally* match 
the names of parts of protocols from being considered such.  
This prevents the problem common in other OOPLs where method names 
accidentally match, causing problems not detected [if ever] until run time.


As always, the proof is in the pudding.  I encourage people new to
OOP to actually *try* several languages in "non-trivial" tasks,
and see how well those languages, and their compilers, meet you needs.
Your smilage will vary.

[Standard disclaimer, these are *my* opinions only.  I do not disagree
 with Bertrand entirely, only in degree.]

bertrand@eiffel.UUCP (Bertrand Meyer) (03/09/90)

From <2628@castle.ed.ac.uk> by nick@lfcs.ed.ac.uk (Nick Rothwell):

> The [Eiffel] type system seems a bit shakey to me.

From <53012@microsoft.UUCP> by jimad@microsoft.UUCP (Jim ADCOCK):

> How can the words 'strong type checking' be applied to a language
> [i.e. Eiffel] that gets its permissions on return types exactly
> backasswards?  Fix your *own* language, before throwing stones, Bertrand!


    Every once in a while someone ``discovers'' that the Eiffel type
system is ``wrong''. The latest printed occurrence I know of is a letter
published in the last JOOP.

    The Eiffel type system is neither ``shakey'' nor wrong. I have
written a long paper (posted in comp.lang.eiffel as
<176@eiffel.UUCP> and <177@eiffel.UUCP> in July of 1989)
explaining why the type rules are what they are. This answered in
particular an earlier paper by William Cook. My paper has not been
published in print (for lack of time and because I will
reuse it as book chapter), but it has been fairly widely circulated
since it was first posted.

    Denying the validity of Mr. Rothwell's statement would be
contradicting a matter on which he is better informed than I am:
his personal opinion regarding the Eiffel type system.
There is no reason to doubt that the statement is true,
although it provides information about Mr. Rothwell, not about Eiffel.

    It is not, however, a very pleasant statement, for impressions are
easy to spread and hard to fight.

    This is like when a person is being criticized: if Paul says Peter
has stolen Paul's car, Peter can defend himself; if Paul spreads
the rumor that Peter is a shady (or shaky) character, what can Peter do?
I have strong opinions, and have not been shy in publicizing what
I think of C++, but I have endeavored to focus on concrete technical
arguments addressing specific points. Reciprocality will be appreciated.

    Mr. Adcock's suggestion is gratefully acknowledged but
Eiffel's type system needs no fixing. I have had some trouble
understanding his message; first I do not know the word ``backasswards'',
although my limited but improving knowledge of English leads me to
gather that this word is not likely to carry an entirely favorable
connotation. Second, I have not heard anyone else criticize the
Eiffel rule for redefining the ``return type'' (which I understand
as the type of a function's result). In Eiffel this has to be a
descendant of the original type, not raising any problem that I know of.

    What has been criticized before (and I must assume this is what
Mr. Adcock really had in mind) is the rule for routine arguments,
which is the same as for results. This shocks many people who approach
the problem from a purely theoretical perspective; the absence of a
precise discussion of this topic in my book ``Object-Oriented Software
Construction'' did not help here. (Obviously I should have been more
careful.)

    Unfortunately for the theoreticians, the Eiffel rule is the one that
makes sense in practice. To take a very simple example, take the generic
class

    LIST [T]

with a procedure

    insert (x: T)

Assume a class and one of its heirs, for example STUDENT and its heir
UNIVERSITY_STUDENT. With the declarations

    sl: LIST [STUDENT] 
    usl: LIST [UNIVERSITY_STUDENT] 

the call ``sl.insert (s)'' should be valid for any s of type STUDENT,
but the call ``usl.insert (s)'' should be valid only for s of type
UNIVERSITY_STUDENT. The ``contrapositive'' rule advocated by some
would require that the version of ``insert'' for class
LIST [UNIVERSITY_STUDENT] take arguments whose types are *ancestors*
of STUDENT! This does not make sense - nor does the rule suggested by
the authors of the JOOP letter, according to whom it should not be
possible to change the argument types. They cite this as being the C++
rule. My congratulations to anyone who can write  useful software
in these conditions. (This is impossible, of course, and is one
of the reasons why undisciplined type casts are constantly needed
in such a context. I think this makes a mockery of
object-oriented ideas.)

    What the above simply means is that type checking in an
object-oriented language is more difficult than what a two-minute
peek at the problem might suggest.

    By the way, Eiffel's genericity (parameterized classes, such as
LIST [T]) only makes the problem more visible; the same argument could
be applied without any use of genericity.

A few more comments:

1. It would be immensely pleasurable if critics of the Eiffel type
rules would work under the assumption that Eiffel's designers,
although they have made mistakes and will undoubtedly make
more, are not *totally* incompetent.

2. In the same vein, our experience may have given us a perspective that
not all outside commentators enjoy. We have written tens of thousands of
lines of typed, reusable object-oriented software, including libraries
that are used daily by hundreds of people. Once again
this does not make us infallible, but I know of very, very few people in
the world today who have that kind of experience, and the appreciation
it gives for what works and what does not.

3. I have seen no one mention what I think is one of Eiffel's
significant contributions: a type system which is fully uniform, and
entirely based on the notion of class. Even integers and booleans are
theoretically based on classes (through ``expanded types''), with no
loss of efficiency at the implementation stage.

4. One thing that does need fixing is the amount of type checking done
by our current compiler, which misses some cases. The reason this has
not been done before is that these cases occur extremely rarely in
practice (for example there has not been a single recorded case in our
company), so that we have devoted our forces to more urgent tasks.
However the situation will be corrected in the next major release.

5. I have known for a long time Luca Cardelli's elegant work
(A Semantics of Multiple Inheritance, in Semantics of Data Types,
edited by Gilles Kahn, David B. McQueen and Gordon Plotkin,
Lecture Notes in Computer Science 173, Springer-Verlag, New York,
1984, pp. 51-67). This denotational model of some of
the properties of inheritance suggests a contrapositive rule.
Enamored as I may be of denotational semantics, however, I think that in
science theories should be made to fit reality, not the other way around.
Physicists are not supposed to change experimental results which do not
agree with the model.

This, of course, assumes somewhat arrogantly that Eiffel's rules
are ``the reality''. Quite frankly, I would prefer the
type rules to be as simple as Cardelli's work suggests but,
as mentioned above, I don't see any other usable solution than Eiffel's.
If someone can come up with a better suggestion, I will be the first
to embrace it. In the meantime, we'll have to live with a useful
practical solution even if it pains the theoreticians. Sorry.

6. Finally, our group does not just talk about Eiffel but also
implements it. The type rules that we use makes type checking more
difficult. Like everyone else we prefer easy jobs to hard jobs;
one more reason to welcome any simpler solution - provided it also
works.

-- Bertrand Meyer
bertrand@eiffel.com

munck@linus.UUCP (Robert Munck) (03/09/90)

I wonder if others have noticed that there's a single strong divisor
in this thread, separating it into two warring groups.  It corresponds
roughly to the C/Ada division, also C/anti-C and anti-Ada/Ada.

Basically, it's the "world view" that programming is a solitary activity
or a communal one.  That is, that programming is done by one person, with
little or no contact with others, or that it's done by a group of some
size, in constant close contact and also spread out in time and space.

That dicotomy obviously splits the university crowd from the military-
industrial crowd; universities have the problem that cooperative work
is called "cheating" in most other areas, so it's difficult for them to
take any other approach to s/w eng.  The m-i complex people have the
problem that they cannot take the risk of entrusting a project to a
single or small number of people because of the possibilities that they
will be hit by a bus, poisoned at the local Chinese restaurant, or leave
the company.

I don't know how the differences can be reconciled.
                          -- Bob Munck, MITRE ==> Unisys (STARS)
-- 
                 -- Bob <Munck@MITRE.ORG>, linus!munck.UUCP
                 -- MS Z676, MITRE Corporation, McLean, VA 22120
                 -- 703/883-6688

woody@eos.UUCP (Wayne Wood) (03/10/90)

In article <101567@linus.UUCP> munck@linus.UUCP (Robert Munck) writes:
>
>That dicotomy obviously splits the university crowd from the military-
>industrial crowd; universities have the problem that cooperative work
>is called "cheating" in most other areas, so it's difficult for them to
>take any other approach to s/w eng.  The m-i complex people have the
>problem that they cannot take the risk of entrusting a project to a
>single or small number of people because of the possibilities that they
>will be hit by a bus, poisoned at the local Chinese restaurant, or leave
>the company.
>
>I don't know how the differences can be reconciled.

just get rid of the M-I complex

:-)

just another '60's throwback
:-)


/***   woody   ****************************************************************
*** ...tongue tied and twisted, just an earth bound misfit, I...            ***
*** -- David Gilmour, Pink Floyd                                            ***
****** woody@eos.arc.nasa.gov *** my opinions, like my mind, are my own ******/

chris@mcc.UUCP (Chris Robertson) (03/12/90)

In article <1990Mar4.005122.14121@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>
>Yeah, I was a C novice once.  I'm glad that all the code I wrote then
>is dead and buried.

Oh no it ain't, Henry -- I saved it all, and it's available to any who
ask for just a modest fee...  hey, I could post sections of it, and we
could all discuss it!  

(I guess I could skip the latter step if you were to to mail me Mucho$ Buck$,
in small bills, in a plain brown wrapper...) 

(It's always nice to feel one's years at University weren't wasted -- of
course, I *was* supposed to be studying Zoology at utzoo, not creative
entrepreneurship and advanced blackmail! ;-)
-- 
"Down in the dumps?  I TOLD you you'd     |    Chris Robertson
 need two sets..."                        |  chris@mcc.pyrsyd.oz

henry@utzoo.uucp (Henry Spencer) (03/14/90)

In article <101@mcc.UUCP> chris@mcc.UUCP (Chris Robertson) writes:
>>Yeah, I was a C novice once.  I'm glad that all the code I wrote then
>>is dead and buried.
>
>Oh no it ain't, Henry -- I saved it all, and it's available to any who
>ask for just a modest fee...  hey, I could post sections of it, and we
>could all discuss it!  

Sorry, Chris, my *real* C-novice days were back before you knew me, and
the code from then really is dead and buried.  Thank heavens. :-)  I'd
been using C for about five years by the time I started working at utzoo.
This is not to say there isn't some slightly embarrassing code from more
recent times...
-- 
MSDOS, abbrev:  Maybe SomeDay |     Henry Spencer at U of Toronto Zoology
an Operating System.          | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

weiner@novavax.UUCP (Bob Weiner) (03/14/90)

not all outside commentators enjoy. We have written tens of thousands of
lines of typed, reusable object-oriented software, including libraries
that are used daily by hundreds of people. Once again
this does not make us infallible, but I know of very, very few people in
the world today who have that kind of experience, and the appreciation
it gives for what works and what does not.
-- 
Bob Weiner, Motorola, Inc.,   USENET:  ...!gatech!uflorida!novavax!weiner

weiner@novavax.UUCP (Bob Weiner) (03/14/90)

[Please pardon and disregard my last message which was inadvertently
posted prior to my writing it.  This is the intended message.]

In article <264@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:

> We have written tens of thousands of
> lines of typed, reusable object-oriented software, including libraries
> that are used daily by hundreds of people.

As a user and supporter of Dr. Meyer's work on Eiffel, I feel qualified
to take exception with his statement above.  I certainly am unaware of
any code that ISE (Dr. Meyer's company) has not yet released publicly
but I hesitate to label the present set of Eiffel class libraries from
ISE as 'tens of thousands of lines of ... reusable ... software'.

It is true that the code may be reused, as may any code, but the present
state of the libraries does not put them in the class of what I believe
any experienced developer would want in reusable classes.  More
precisely:

There are no performance characteristics given with any of the classes.

There is little in the way of documentation explaining the protocols
used by each class and the single line public comments associated with
most class features (routines and attributes) mask some often needed
information about the code internals.  That is, very often the external
specifications of features in these classes are quite incomplete.

There is hardly any internal feature documentation.

The class indexing provided with V2.2 is extremely spotty.


I should also say that most of these libraries do work as expected and
ISE is very generous with their source code licensing.  Additionally,
AT&T provides no significant class library with their C++ compiler;
hence I would definitely choose a broad working class library over none
at all (such commercially supported libraries will come, but they are
not here today).

My main point is that I simply can't imagine developing a system that
uses the Eiffel libraries without examining the source code.  Development
through conformance to external specifications is truly my hope for when
we reach the dawn of 'reusable software components'.
-- 
Bob Weiner, Motorola, Inc.,   USENET:  ...!gatech!uflorida!novavax!weiner