[comp.lang.c] comma operator: keep away?

jas@ernie.Berkeley.EDU (Jim Shankland) (04/18/89)

In article <628@gonzo.UUCP> daveb@gonzo.UUCP (Dave Brower) writes:
[A long diatribe against use of the comma operator in all contexts except
macro bodies, and, sometimes, "for" loop initialization and continuation.]

Granted, everyone should write code that is easily understandable by
others.  Granted, also, that the way to do that depends on idioms in
common use in a particular language:  constructs that are common usage
in, e.g., LISP, may be obscure in C.  Granted, finally, that it is quite
possible to write obscure C code by using the comma operator (and in
countless other ways).

I still suggest that a C programmer who understands:

(A)	if (x->in_use)
	{
		x++;
		y++;
	}

but who is mystified by:

(B)	if (x->in_use)
		x++, y++;

had best be investigating alternate career paths.

The goal daveb@gonzo is pursuing is an admirable one:  how can we get
programmers, especially masses of programmers, to write code that
is correct, understandable, and modifiable by others, in reasonable
time?  It is certainly one of the most important questions in
programming, and answers have been slow in coming.  I understand
and sympathize with the temptation to tilt at windmills; but it
won't kill the dragons.

The world is full of bad programmers.  A magic potion that would turn
them all into good programmers would be a useful thing, indeed.
Brings to mind the (surely apocryphal) story about the ne'er-do-wells
who finagled an NSF grant to research ways to turn cow shit into butter.
Having partied away the entire grant, they applied for supplemental
funds, with the argument:  "We've gotten it to spread like butter,
now we need more money to work on the taste."

Exorcising the comma operator from bad code may make it spread better.
The taste, alas, remains unchanged.

Jim Shankland
jas@ernie.berkeley.edu

"Blame it on the lies that killed us, blame it on the truth that ran us down"

bill@twwells.uucp (T. William Wells) (04/19/89)

In article <28831@ucbvax.BERKELEY.EDU> jas@ernie.Berkeley.EDU (Jim Shankland) writes:
: I still suggest that a C programmer who understands:
:
: (A)   if (x->in_use)
:       {
:               x++;
:               y++;
:       }
:
: but who is mystified by:
:
: (B)   if (x->in_use)
:               x++, y++;
:
: had best be investigating alternate career paths.

The thing that is wrong with the latter has little to do with
mystification. What is wrong is that, for rapid and accurate
understanding of code, one should avoid appearing to do more than one
thing at a time.

In other words, the physical layout of the code should make each thing
being done appear distinct from all the other things being done.

How often have you been burned by missing the second part of a comma
operator? How frequently have you missed the assignment is some
idiocy like:

	foo(<long---complicated---expression, ((bletch = 1) * glorch);

And how often have you missed the significance of an expression that
is pasted on the end of an if? As in awful code like:

		if (expression) { statement;
		statement;      /*!*/
	}

Look rapidly at the examples following the form feed.

Which one would you understand most quickly? And which one, after a
quick glance, would you believe you had understood more accurately?


	if (!(fp1 = fopen(name1, "r")) || !(fp2 = fopen(name2, "r"))) {
		error();
	}

	if (  !(fp1 = fopen(name1, "r"))
	   || !(fp2 = fopen(name2, "r"))) {
		error();
	}

The point is that the latter makes it clear that two different things
are happening. The former you have to figure this out for yourself.

The cost is in time, and if you are just skimming the code, in
immediate comprehension.

Of course, such differences are trivial in any given fragment of code,
but when carried out throughout the program, they can make the
difference between code that is easy to understand and code whose
reading feels like wading through a swamp.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

rupley@arizona.edu (John Rupley) (04/19/89)

In article <28831@ucbvax.BERKELEY.EDU>, jas@ernie.Berkeley.EDU (Jim Shankland)
writes:
> The world is full of bad programmers.  A magic potion that would turn
> them all into good programmers would be a useful thing, indeed.
> Brings to mind the (surely apocryphal) story about the ne'er-do-wells
> who finagled an NSF grant to research ways to turn cow shit into butter.
> Having partied away the entire grant, they applied for supplemental
> funds, with the argument:  "We've gotten it to spread like butter,
> now we need more money to work on the taste."

Ah, but the __true__ story is even better......

At a meeting of the National Academy, in 1967 I believe, there was a
panel discussion with several significant bureaucrats from the NSF and
NIH.  They floated the idea that science funding should be partly if
not largely through block grants to Universities, whose administrators
would have the power to distribute the funds.  This horrifying concept
prompted a response from Kistiakowsky (kinetics, explosions, atom bomb,
Eisenhower, science advisor -- for those too young in years to
remember).  He rose from the audience and said that the proposal
reminded him of conversations he had had with a Soviet Academician.
Several years previously, the Academician had described the Russian
project to convert shit into butter.  Subsequently, Kistiakowsky
recounted, the Academician told him the project was half completed --
they had learned to spread it on bread.  Metaphor complete,
Kistiakowsky returned to his seat.

John Rupley
rupley!local@megaron.arizona.edu

crossgl@ingr.com (Gordon Cross) (04/20/89)

In article <828@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
>
>The thing that is wrong with the latter has little to do with
>mystification. What is wrong is that, for rapid and accurate
>understanding of code, one should avoid appearing to do more than one
>thing at a time.
>
>In other words, the physical layout of the code should make each thing
>being done appear distinct from all the other things being done.

I'd like to make one small observation about Mr. Wells' above comment.  In
certain cases where execution speed is of primary importance and you don't
have the time or energy to code in assembler (God forbid!) the vast majority
of compilers (that I've seen anyway) tend to generate better code for a single
complex expression that accomplishes multiple (related) tasks than for the
equivalent multiple simple expressions.  For example an "insert into doubly
linked list" operation on my compiler:

This one used 4 instructions -

  (new->next = next)->prev = (new->prev = prev)->next = new;

This one used 7 instructions -

  new->next  = next;
  new->prev  = prev;
  next->prev = new;
  prev->next = new;
-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

bill@twwells.uucp (T. William Wells) (04/21/89)

In article <28847@ucbvax.BERKELEY.EDU> jas@ernie.Berkeley.EDU (Jim Shankland) writes:
: In article <828@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
: [again saying the comma operator is unclear, because it doesn't adequately
: separate two distinct operations; also, giving a couple of examples
: of slightly obscure code, with suggestions for improving readability.]
:
: I claim that when the operations are closely related, such as walking
: down two arrays in lockstep, the comma is adequate separation, and is
: arguably clearer -- and certainly more concise -- than a compound statement.

It depends. I often use various devices that break one or more
"rules".  E.g., the notion of splitting up separate operations might
well be thought to require as a rule that one put exactly one
operation per line. However, there are many cases where I don't do
this. One of my favorite examples is in a state machine, one which
looks like this:

	while (1) {
		switch (state) {
		case ST_FOO: act_foo();         state = ST_BAR;      continue;
		case ST_BAR: act_bar();         state = ST_BLETCH;   continue;'
		...
		case ST_DONE:                                           break;
		}
		break;
	}

I claim that, if it can be made clear in this way, that it is better
than the "put one thing on one line" approach. Certainly, I see it
that way.

: I was really trying to make a meta-point:  writing good, clear code
: is a lot more complicated than following a few simple rules.  Rules
: like, "Don't use the comma operator" are neither necessary nor sufficient
: to enforce good coding.  Effort spent inventing and enforcing such rules
: is better spent elsewhere.

I agree with all but the last sentence. There are two distinct
reasons:

    1) Having a set of default rules means that one doesn't have to
       spend lots of time re-inventing the wheel. One just writes the
       code according to the standard and, only when that appears
       inadequate, does one have to spend the time to design the
       appropriate layout of your text.

    2) Having a set of default rules also results in consistency in
       the final product. This consistency is important in that it
       makes maintenance easier and more reliable. Since there are
       many essentially arbitrary choices to make in code layout, if
       there were no standards, there would be many different ways of
       doing exactly the same things, resulting in more difficult to
       understand code.

I wrote a coding standard document for Proximity; here is its
introduction:

	This document contains a description of Proximity's C coding
	conventions and practices.  It describes rules for naming
	files and symbols, and outlines the format of source and
	include files.  It also discusses the use of Proxlib and the
	standard C library routines.  The benefits of these coding
	practices are threefold: the code is (1) more easily
	understandable, (2) more easily ported between systems, an
	important feature in Proximity products, and (3) more likely
	to work the first time and be free of hidden bugs.

	These rules should be followed in most code, but unusual
	situations may require unusual code. When breaking these
	rules, unless it is obvious from the context, you must include
	a comment stating why you broke them. This reason must be
	equivalent to ``Something bad will happen if I follow the
	rule'' rather than ``Something good will happen if I break the
	rule''. Thus, if you have a piece of code whose fast
	execution is essential to the quality of the product in which
	it is embedded, it would be proper to include a rule-violating
	hack. If, on the other hand, you have a neat trick which would
	make the program faster or smaller, when such is unnecessary,
	but which would break one of these rules or which would make
	the program unclear: DON'T DO IT!

	There are situations when it would be a good idea to modify
	some of these rules. If you run into one of these, discuss it
	with your project leader (or the head of the software
	department if you are the project leader). Then, assuming you
	can agree on the modification, go ahead and use your modified
	rule, but until you have had this document updated, comment
	your use. Also, tell the person responsible for this document
	about the rule change.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

bill@twwells.uucp (T. William Wells) (04/21/89)

In article <5053@ingr.com> crossgl@ingr.UUCP (Gordon Cross) writes:
: I'd like to make one small observation about Mr. Wells' above comment.  In
: certain cases where execution speed is of primary importance and you don't
: have the time or energy to code in assembler (God forbid!) the vast majority
: of compilers (that I've seen anyway) tend to generate better code for a single
: complex expression that accomplishes multiple (related) tasks than for the
: equivalent multiple simple expressions.  For example an "insert into doubly
: linked list" operation on my compiler:
:
: This one used 4 instructions -
:
:   (new->next = next)->prev = (new->prev = prev)->next = new;
:
: This one used 7 instructions -
:
:   new->next  = next;
:   new->prev  = prev;
:   next->prev = new;
:   prev->next = new;

But, counterintuitively, one VAX compiler given the following:

	x = y = z = 0;

generated worse code than

	x = 0;
	y = 0;
	z = 0;

Why? Because the compiler chose to interpret the first one according
to its letter rather than its spirit, generating:

	move    z,0
	move    y,z
	move    x,y

instead of the better:

	move    z,0
	move    y,0
	move    x,0

or even:

	move    register,0
	move    z,register
	move    y,register
	move    x,register

And the compiler that did this would have compiled both of the
examples with only four instructions.

The moral? Unless you a) have reason to believe that the speed is
going to make a difference, and b) are willing to read assembly code
to verify that your coding hack really makes a difference, follow
your style rules rather than doing speed hacks.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

bobmon@iuvax.cs.indiana.edu (RAMontante) (04/22/89)

Just to keep this thread from dying its well-deserved death . . . .

Is there a circumstance in which the comma operator is required, where
the compound statement cannot be broken into multiple statements?

gwyn@smoke.BRL.MIL (Doug Gwyn) (04/22/89)

In article <19913@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>Is there a circumstance in which the comma operator is required, where
>the compound statement cannot be broken into multiple statements?

You've got to be kidding -- a comma expression is an expression,
whereas multiple statements are not an expression.  Thus the comma
operator is useful in contexts where semicolon-terminated statements
would not be.  Look at the definition of putc() in most implementations
of <stdio.h> for an example.

bobmon@iuvax.cs.indiana.edu (RAMontante) (04/23/89)

gwyn@brl.arpa (Doug Gwyn) <10092@smoke.BRL.MIL> :
-	[ me ]
->Is there a circumstance in which the comma operator is required, where
->the compound statement cannot be broken into multiple statements?
-
-You've got to be kidding -- a comma expression is an expression,
-whereas multiple statements are not an expression.  Thus the comma
-operator is useful in contexts where semicolon-terminated statements
-would not be.  Look at the definition of putc() in most implementations
-of <stdio.h> for an example.


"You've got to be kidding?" In fact someone else suggested getchar() as
an example.  Looking at the Turbo C stdio.h, and the ULTRIX v1.7 stdio.h,
I find that neither one uses a comma in getc, getchar, putc, putchar, or
anywhere else, except to separate parameters.

Nonetheless I think I get the idea, but that doesn't mean that the code
wouldn't work without the comma (does it?) -- couldn't the same semantics
be reproduced by a series of statements culminating in the final
expression of the parentheses (presumably for assignment purposes)?

I said "required", not "useful".

bill@twwells.uucp (T. William Wells) (04/23/89)

In article <19913@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
: Is there a circumstance in which the comma operator is required, where
: the compound statement cannot be broken into multiple statements?

Certainly, though I'd not say "required", just "much better
programming": in macros and in the initialization and update parts of
for statements. And I'm sure I could think of a few more if I spent
the time.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

gwyn@smoke.BRL.MIL (Doug Gwyn) (04/23/89)

In article <19926@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>I find that neither one uses a comma in getc, getchar, putc, putchar, or
>anywhere else, except to separate parameters.

Ok, I picked a bad example.  However, many macros need to accomplish
more than one thing and cannot do so without the aid of some such
trickery as
	((expr1) & 0 | (expr2))
which is more simply expressed as
	(expr1, expr2)

>Nonetheless I think I get the idea, but that doesn't mean that the code
>wouldn't work without the comma (does it?) -- couldn't the same semantics
>be reproduced by a series of statements culminating in the final
>expression of the parentheses (presumably for assignment purposes)?

No!  A series of statements cannot be used as a subexpression.

Of course -- as I just demonstrated -- there are ways to avoid ever using
a comma operator, but then all you really need is a Turing machine, right?
So why does C provide more than the logical minimum?  It's because it was
designed to be USED for real programming, and matters of convenience are
quite relevant for that.

sho@pur-phy (Sho Kuwamoto) (04/23/89)

In article <19926@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
<gwyn@brl.arpa (Doug Gwyn) <10092@smoke.BRL.MIL> :
<<	[ me ]
<<<Is there a circumstance in which the comma operator is required, where
<<<the compound statement cannot be broken into multiple statements?
<<
<<You've got to be kidding << a comma expression is an expression,
<<[..]
<[..]
<Nonetheless I think I get the idea, but that doesn't mean that the code
<wouldn't work without the comma (does it?) -- couldn't the same semantics
<be reproduced by a series of statements culminating in the final
<expression of the parentheses (presumably for assignment purposes)?

When it comes right down to it, there are lots of unneccessary features.
for, while, case, do while, the entire preproccessor, array indexing,
->, ?:, structs, unions, etc.  All of these could be done with goto and
explicit pointer manipulation, etc., if you wanted to.  But why?

As for another example where you could use the comma operator usefully,
how about...

	for(i=0, p=head; p->next != NULL; i++, p=p->next)
or something.

-Sho

wietse@wzv.UUCP (Wietse Z. Venema) (04/23/89)

bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>Is there a circumstance in which the comma operator is required, where
>the compound statement cannot be broken into multiple statements?

"... in macros where a multistep computation has to be a single expression."
					K&R second edition, page 63.
-- 
work:	wswietse@eutrc3.uucp	| Eindhoven University of Technology
work:	wswietse@heitue5.bitnet	| Mathematics and Computing Science
home:	wietse@wzv.uucp		| Eindhoven, The Netherlands

bobmon@iuvax.cs.indiana.edu (RAMontante) (04/24/89)

[ me ]
>Is there a circumstance in which the comma operator is required, where
>the compound statement cannot be broken into multiple statements?

wietse@wzv.UUCP (Wietse Z. Venema) <268@wzv.UUCP> :
-
-"... in macros where a multistep computation has to be a single expression."
-					K&R second edition, page 63.

I see that now, and thank you everybody.  I find that when I originally
posed the question I was mentally excluding macros from consideration, a
curious lapse I admit.

(BTW:  I didn't mean to sound anti-comma.)

bink@aplcen.apl.jhu.edu (Ubben Greg) (04/24/89)

In article <2179@pur-phy> (Sho Kuwamoto) writes:
>[...]
>As for another example where you could use the comma operator usefully,
>how about...
>
>	for(i=0, p=head; p->next != NULL; i++, p=p->next)
>or something.

Right idea, but bad example.  People too often cram expressions in the
for(;;) that are not related to the loop control, just to avoid a couple of
extra lines.  I admit that I do it myself.  In this case, the execution of
the loop is totally dependent on the contents of the linked list.  It would
be more clearly written as:
	i = 0;
	for (p=head; p->next!=NULL; p=p->next) {
		/*  I normally use "p" instead of "p->next!=NULL" */
		/*  We're skipping the last item here.            */
		i++;
	}
It's especially hard to resist this when the for expression would otherwise
be null.  I would be tempted to hide the i=0 in its declaration and the i++
in an expression, but this is arguably also bad.  Actually, I'm not all that
firm on this opinion.  Comments?

					-- Greg Ubben
					   bink@aplcen.apl.jhu.edu

peter@ficc.uu.net (Peter da Silva) (04/24/89)

In article <1104@aplcen.apl.jhu.edu>, bink@aplcen.apl.jhu.edu (Ubben Greg) writes:
> In article <2179@pur-phy> (Sho Kuwamoto) writes:
> >	for(i=0, p=head; p->next != NULL; i++, p=p->next)

> People too often cram expressions in the for(;;) that are not related
> to the loop control, just to avoid a couple of extra lines.

I dispute that's the motivation in this case. But putting the i=0 and i++
in the loop you're providing extra information: that the variable 'i' is
tightly bound to the loop, and may be serving as a manufactured loop index.
The alternative:

	i = 0;
	for(p=head; p->next != NULL; p=p->next)
	{
		...
		i++;
	}

implies that 'i' might not be bound to the loop, and also means that you
would have to special-case any 'continue' statement in the expression if it
is so bound.

		if(gottagetouttahere)
			i++, continue;	/* :-> */

(Yes, I know you can't do that).
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

kremer@cs.odu.edu (Lloyd Kremer) (04/24/89)

In article <19913@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante)
writes:
>Is there a circumstance in which the comma operator is required, where
>the compound statement cannot be broken into multiple statements?

Perhaps not required, but convenient nevertheless.

I often use it for loop tests using functions that "get" information but
do not "return" the information they get.  For example:

	extern double frexp();
	double f[SIZE];
	int i, exp;

	...
	while(frexp(f[i++], &exp), exp < 10)
		statement;
	...

Another example would be:

	char c;

	while(read( ..., &c, 1), c != '\n')

assuming EOF detection is not needed for this read() (horrible assumption,
I know).

-- 
					Lloyd Kremer
					Brooks Financial Systems
					...!uunet!xanth!brooks!lloyd
					Have terminal...will hack!

henry@utzoo.uucp (Henry Spencer) (04/25/89)

In article <28831@ucbvax.BERKELEY.EDU> jas@ernie.Berkeley.EDU (Jim Shankland) writes:
>I still suggest that a C programmer who understands:
>
>(A)	if (x->in_use)
>	{
>		x++;
>		y++;
>	}
>
>but who is mystified by:
>
>(B)	if (x->in_use)
>		x++, y++;
>
>had best be investigating alternate career paths.

This is very true.  On the other hand, a C programmer who writes the latter
should also be investigating alternate career paths, because he's clearly
an amateur in a business that needs professionals.  Anyone who says "any
competent programmer ought to be able to understand that!" rather than
"I should make my code as clear as possible!" is an amateur, and one with
an ego problem at that.  Readability is very much a matter of what you're
used to.  Like it or lump it, most C programmers are used to (A) and not (B).
A programmer with a professional attitude will therefore use (A) to make his
code as readable as possible, unless there is some special reason to do
otherwise.

To quote #8 from the Ten Commandments for C Programmers:

	Thou shalt make thy program's purpose and structure
	clear to thy fellow man by using [a familiar style],
	even if thou likest it not, for thy creativity is better
	used in solving problems than in creating beautiful new
	impediments to understanding.
-- 
Mars in 1980s:  USSR, 2 tries, |     Henry Spencer at U of Toronto Zoology
2 failures; USA, 0 tries.      | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

les@chinet.chi.il.us (Leslie Mikesell) (04/25/89)

In article <19926@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>->Is there a circumstance in which the comma operator is required, where
>->the compound statement cannot be broken into multiple statements?

>I said "required", not "useful".

How about the more common:

for (x=0, y=0; x <100 ; x++, y++) {
    stuff ...
}
 
Of course this could also be done other ways - the only thing "required"
in a programming language is an assignment and a test-and-branch operator.
The rest is merely "useful".

Les Mikesell
 

ddb@ns.network.com (David Dyer-Bennet) (04/25/89)

In article <10098@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
:Ok, I picked a bad example.  However, many macros need to accomplish
:more than one thing and cannot do so without the aid of some such
:trickery as
:	((expr1) & 0 | (expr2))
:which is more simply expressed as
:	(expr1, expr2)

Which is an example of the weakness of the macro facility in C (one of the
most light-weight macro facilities I've ever had foisted on me).  Without
taking a position on the general value of the comma operator -- the correct
solution to this one is to improve the macro facility, not provide a
way to kludge some (but not all) cases.
-- 
David Dyer-Bennet, ddb@terrabit.fidonet.org, or ddb@ns.network.com
or ddb@Lynx.MN.Org, ...{amdahl,hpda}!bungia!viper!ddb
or ...!{rutgers!dayton | amdahl!ems | uunet!rosevax}!umn-cs!ns!ddb
or Fidonet 1:282/341.0, (612) 721-8967 9600hst/2400/1200/300

jas@ernie.Berkeley.EDU (Jim Shankland) (04/25/89)

In article <1989Apr24.172219.817@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>On the other hand, a C programmer who [uses a comma operator to sequence
>two closely related expression evaluations, instead of two statements]
>should ... be investigating alternate career paths, because he's clearly
>an amateur in a business that needs professionals.  Anyone who says "any
>competent programmer ought to be able to understand that!" rather than
>"I should make my code as clear as possible!" is an amateur, and one with
>an ego problem at that.  Readability is very much a matter of what you're
>used to.  Like it or lump it, most C programmers are used to [the compound
>statement] and not [the comma construct].

Sigh.  Must have been lousy weather in Toronto that morning.

We're agreed that a professional programmer should code as clearly
and readably as possible, and that gratuitous cleverness is a bad
thing.  My original posting said so.  What I consider self-evidently
true, and you consider self-evidently false, is that the comma
construct is sometimes at least as clear as the equivalent compound
statement.  Short of running code comprehension experiments on
hundreds of bad C programmers, I don't see how we can resolve our
difference of opinion.  But at least I haven't questioned your
professionalism.

Now look what you've done.  Made me grumpy.  Not, on the whole, an
easy thing to do.

Jim Shankland
jas@ernie.berkeley.edu

"Blame it on the lies that killed us, blame it on the truth that ran us down"

friedl@vsi.COM (Stephen J. Friedl) (04/25/89)

In article <1989Apr24.172219.817@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> Anyone who says "any competent programmer ought to be able to understand
> that!" rather than "I should make my code as clear as possible!" is an
> amateur, and one with an ego problem at that.

When writing software, always assume that the next person reading
your code will be somebody much less qualified than you, and they
will be required to fix a very hot bug with little time for study.

You'll probably be right.

     Steve

-- 
Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 
3B2-kind-of-guy   / friedl@vsi.com  / {attmail, uunet, etc}!vsi!friedl

As long as Bush is in office, you'll never see Nancy Reagan in *my* .sig.

mat@mole-end.UUCP (Mark A Terribile) (04/25/89)

In article <1104@aplcen.apl.jhu.edu>, bink@aplcen.apl.jhu.edu (Ubben Greg) writes:
> In article <2179@pur-phy> (Sho Kuwamoto) writes:

> >As for another example where you could use the comma operator usefully,
> >how about...

> >	for(i=0, p=head; p->next != NULL; i++, p=p->next)


> Right idea, but bad example.  People too often cram expressions in the
> for(;;) that are not related to the loop control, just to avoid a couple of
> extra lines.  ... the execution of the loop is totally dependent on the
> contents of the linked list.  ...

In this case, I respectfully disagree.

Since the point of the loop is to establish a relationship between the
number of items in the linked list and the value of  i , and since the
code that manipulates  i  is quite short, I prefer the ``compact'' form.
Just be sure to write the null statement as something more than an
unadorned semicolon.  I like    /* NULL */ ;   and    {}   best myself.

Even if there is something else that must be done each time around, I would
prefer to put lockstep counting in the loop control; it reduces the
likelyhood that someone who comes along later to do bodacious things to the
other code will mess up this important but hard-to-see-for-its-small-size
counting code.

Oh, and I *definately* *would* *not* put the initialization of  i  in the
declaration unless it were a nested local declaration whose scope began
right before the for(;;) and expired right after the for(;;).  Even then
I'd have some doubts.  The initialization to zero is part of establishing
that relationship between the cardinality of the linked list (if I may
express the thing that way) and the value of  i .
-- 

(This man's opinions are his own.)
From mole-end				Mark Terribile

toddpw@tybalt.caltech.edu (Todd P. Whitesel) (04/25/89)

a side note about this comma brouhaha:

 on a convex x-mp running convex unix, a code fragment such as

 foo (parm1,parm2), foo2 (parm1,parm2);

is illegal and gets you screens full of syntax errors from both lint and cc.

hmmm.....

toddpw @ caltech.bitnet
toddpw @ romeo.caltech.edu

crewman@bucsb.UUCP (JJS) (04/26/89)

In article <1989Apr24.172219.817@utzoo.uucp> (Henry Spencer) writes:
>
>On the other hand, a C programmer who [uses a comma operator to sequence
>two closely related expression evaluations, instead of two statements]
>should ... be investigating alternate career paths, because he's clearly
>an amateur in a business that needs professionals.  Anyone who says "any
>competent programmer ought to be able to understand that!" rather than
>"I should make my code as clear as possible!" is an amateur, and one with
>an ego problem at that.  Readability is very much a matter of what you're
>used to.  Like it or lump it, most C programmers are used to [the compound
>statement] and not [the comma construct].
>

I believe that should read, 'most *Pascal* programmers are used to the compound
statement and not the comma construct'.  This is just my opinion, and one
with which many people differ, but why are C programmers always advised not
to use the unique features of C?  So far, I've been advised against:

	-- using the comma construct
	-- using the (a ? b : c) expression
	-- using an assignment as a function
	-- using "if (a)" instead of "if (a != 0)"
	-- using += -= *= /= |= &= ^=
	-- using << >> <<= >>=
	-- using complex pointer-integer expressions
	-- generally complex expressions: map |= (line[k++] = string[j++]);
	-- writing compact source code
	etc.

I've also been advised to go out of my way to make my C programs look like
programs written in another language:

#define begin 	{
#define end	}
#define then			/* if (a == 1) then return; */
#define when	break; case	/* when 'a': foo(); when 'b': bar() */
#define otherwise break; default: /* otherwise baz(); */
etc.

Getting back to the poster of the above article, why is the person who likes
the comma construct an amateur?  Is it because s/he likes a unique feature
of C?  Or is it really because the above "professional" would get confused
reading such code?  In a business which so sorely "needs professionals", why
are we bending over backwards to make our programs easier to read for ama-
teurs?

C is designed to be a low-level language.  It's advantage over machine
language and even higher-level languages is its power derived from its
simplicity and compactness.  It is in this way an elegant language; as
C programmers, we have the tools to make powerful programs compact.  Yet
we are constantly advised to throw away these tools.  I believe that
that is VERY unprofessional.

I repeat: this is just my opinion so mail flames to me.

                  -- JJS

diamond@diamond.csl.sony.junet (Norman Diamond) (04/26/89)

In article <19926@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:

>>>>Is there a circumstance in which the comma operator is required, where
>>>>the compound statement cannot be broken into multiple statements?
>>>
>>I said "required", not "useful".

In article <8284@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:

>How about the more common:
>
>for (x=0, y=0; x <100 ; x++, y++) {
>    stuff ...
>}
> 
>Of course this could also be done other ways - the only thing "required"
>in a programming language is an assignment and a test-and-branch operator.
>The rest is merely "useful".

Why two operators?  The sole required operator is "subtract, assign, and
branch if negative."

Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
  The above opinions are my own.   |  Why are programmers criticized for
  If they're also your opinions,   |  re-inventing the wheel, when car
  you're infringing my copyright.  |  manufacturers are praised for it?

henry@utzoo.uucp (Henry Spencer) (04/27/89)

In article <28890@ucbvax.BERKELEY.EDU> jas@ernie.Berkeley.EDU.UUCP (Jim Shankland) writes:
>Sigh.  Must have been lousy weather in Toronto that morning.

No, actually, the Toronto weather's been fine.

>We're agreed that a professional programmer should code as clearly
>and readably as possible, and that gratuitous cleverness is a bad
>thing.  My original posting said so.  What I consider self-evidently
>true, and you consider self-evidently false, is that the comma
>construct is sometimes at least as clear as the equivalent compound
>statement...

As my original posting said, it is a well-established fact, backed by
various experiments on things like reading rates, that familiar styles
are easier to read.  This particular comma construct is uncommon and
hence likely to be unfamiliar.  QED.

There are always unusual cases where the usual style is, for some special
reason, less clear than some variant.  But these are unusual cases, and
should not be taken to indicate acceptable variation in normal code.
-- 
Mars in 1980s:  USSR, 2 tries, |     Henry Spencer at U of Toronto Zoology
2 failures; USA, 0 tries.      | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

gwyn@smoke.BRL.MIL (Doug Gwyn) (04/27/89)

In article <1989Apr26.214622.10697@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>As my original posting said, it is a well-established fact, backed by
>various experiments on things like reading rates, that familiar styles
>are easier to read.  This particular comma construct is uncommon and
>hence likely to be unfamiliar.  QED.

Oh, come on, Henry, what is "common" or "familiar" depends very much
on one's experience.  There are many common cases of truly horrible
coding style, and most of us are familiar with examples of it.  That
in itself does not make it easier to read, desirable, or anything
else along those lines.  The best one can say is that familiarity is
one positive factor in code readability, but there are many others too.
Clear logical structure is probably more important.

While I don't recommend unbridled use of comma operators in place of
semicolons, neither would I call usage such as
	while ( norm( x, y, z ) < distance )
		++x, ++y, ++z;
"unreadable".  It seems to me that it would be perfectly readable
to anyone who should be attempting to deal with C code at all.  It may
even be preferable to adding the extra punctuation that you recommend.

bagpiper@oxy.edu (Michael Paul Hunter) (05/02/89)

In article <28831@ucbvax.BERKELEY.EDU> jas@ernie.Berkeley.EDU (Jim Shankland) writes:
>Granted, everyone should write code that is easily understandable by
>others.  Granted, also, that the way to do that depends on idioms in
>common use in a particular language:  constructs that are common usage
>in, e.g., LISP, may be obscure in C.  Granted, finally, that it is quite
>possible to write obscure C code by using the comma operator (and in
>countless other ways).

With a finite language (finite number of symbols), a finite number of states,
and a finite length program, I believe that you are only going to get
a countable (finite) number of ways to write obscure code... :)
maybe large...but finite!

				       mike