[comp.lang.c] A question of style

roy@phri.nyu.edu (Roy Smith) (11/24/89)

Would you be confused and/or grossed out if you saw:

	if (something)
		perror ("message"), exit(1);
-- 
Roy Smith, Public Health Research Institute
455 First Avenue, New York, NY 10016
{att,philabs,cmcl2,rutgers,hombre}!phri!roy -or- roy@alanine.phri.nyu.edu
"The connector is the network"

bill@twwells.com (T. William Wells) (11/25/89)

In article <1989Nov23.170838.10376@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes:
: Would you be confused and/or grossed out if you saw:
:
:       if (something)
:               perror ("message"), exit(1);

Yes. In particular, that statement contains a "hidden" control
structure: the exit().

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

poser@csli.Stanford.EDU (Bill Poser) (11/26/89)

In article <1989Nov23.170838.10376@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes:
>Would you be confused and/or grossed out if you saw:
>
>	if (something)
>		perror ("message"), exit(1);
>-- 


In addition to having a hidden control structure, I strongly urge you not
to omit braces. I would write:

	if(something){
		somethingelse
	}

This makes the structure much clearer when this is embedded in a lot
of other code, and reduces the likelihood of errors when you add something
to the action taken if the condition is true.

henry@utzoo.uucp (Henry Spencer) (11/26/89)

In article <1989Nov23.170838.10376@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes:
>Would you be confused and/or grossed out if you saw:
>	if (something)
>		perror ("message"), exit(1);

I think the correct word is "wary".  My reaction would be "uh-oh -- this
programmer is putting his own convenience and the joys of clever coding
above readability and maintainability -- better treat this code as an
amateur production and not rely on it too much".

If you do perror-and-exit a lot, package it up as a utility function.
If you don't do it much, write it out the normal way.  Your successors
will thank you.
-- 
That's not a joke, that's      |     Henry Spencer at U of Toronto Zoology
NASA.  -Nick Szabo             | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

jeffa@hpmwtd.HP.COM (Jeff Aguilera) (11/28/89)

> I think the correct word is "wary".  My reaction would be "uh-oh -- this
> programmer is putting his own convenience and the joys of clever coding
> above readability and maintainability -- better treat this code as an
> amateur production and not rely on it too much".

I guess you would object to this C++ code as well:

    short recognize::operator()()
    {
        if (!head) head=1,activate(); //avoid superfluous activations
        if (zero) tail=1; //recognize epsilon-transition
        return tail;
    }

    short recognize::operator<<(int n)
    { 
        if (tail=0,head|body) //turn machine off; scan only if internal states are active
            if ((this->*scan)(n),head=tail&&many) activate(); //Thompson's construction for Kleene closure
        return tail;
    }

I'm sure you object to

    1) nonintuitive operator overloading
    2) proper use of comma expression
    3) long lines
    4) terse comments, not aligned with tabstops
    5) use of = in if () statement
    6) avoidance of newlines
    7) avoidance of braces
    8) individualistic programming styles
    9) code that works so well it requires no maintenance
       (because I have a mathematical modeling proving that
       it works)

-----
jeffa

hascall@atanasoff.cs.iastate.edu (John Hascall) (11/28/89)

In article <???> henry@utzoo.uucp (Henry Spencer) writes:
}In article <???> roy@phri.nyu.edu (Roy Smith) writes:
}>Would you be confused and/or grossed out if you saw:
}>	if (something)
}>		perror ("message"), exit(1);
 
}I think the correct word is "wary"...
}If you do perror-and-exit a lot, package it up as a utility function.

   Or as a macro:

     #define COMPLAIN_AND_DIE(msg) perror(msg),exit(1)

     if (something) COMPLAIN_AND_DIE("message");

John Hascall

henry@utzoo.uucp (Henry Spencer) (11/29/89)

In article <680013@hpmwjaa.HP.COM> jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
>> I think the correct word is "wary".  My reaction would be "uh-oh -- this
>> programmer is putting his own convenience and the joys of clever coding
>> above readability and maintainability -- better treat this code as an
>> amateur production and not rely on it too much".
>
>I guess you would object to this C++ code as well:

I'm afraid so.

>I'm sure you object to
>
>    1) nonintuitive operator overloading

Depends on what is being done.  I'd certainly be very cautious about it.

>    2) proper use of comma expression

Depends on what "proper" means.  There is a difference between what a
compiler will accept and what a human can read easily.

>    3) long lines

They do cause trouble at times.

>    4) terse comments, not aligned with tabstops

Terseness I have no objection to, although messy formatting of any code
does make code harder to read.

>    5) use of = in if () statement

By and large, yes.

>    6) avoidance of newlines

Yes.  White space is not the tool of the devil, quite the contrary.

>    7) avoidance of braces

Yes.

>    8) individualistic programming styles

On the whole, yes.  Code should be intelligible to your successors, not
just to you.  This means giving up a certain amount of individuality.
Contrary to popular superstition, this does not shackle your creative
ability, it just directs it into more productive channels.  Remember the
artists' maxim:  "form liberates".

>    9) code that works so well it requires no maintenance
>       (because I have a mathematical modeling proving that
>       it works)

1. I don't care whether *you* are sure it works; what I want to know is
	whether *I* can easily assure myself it works.

2. Do you have a program that takes your source and your proof as input
	and verifies that they are consistent?  If not, then you have
	verified the correctness of your model, not your program, and
	it is important that your program be readable, so that a *human*
	can verify that it implements the model correctly.

3. What happens when the spec changes?  Then it *will* require maintenance.
-- 
That's not a joke, that's      |     Henry Spencer at U of Toronto Zoology
NASA.  -Nick Szabo             | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

amull@Morgan.COM (Andrew P. Mullhaupt) (11/29/89)

In article <680013@hpmwjaa.HP.COM>, jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
> > I think the correct word is "wary".  My reaction would be "uh-oh -- this
> > programmer is putting his own convenience and the joys of clever coding
> > above readability and maintainability -- better treat this code as an
> > amateur production and not rely on it too much".
>
... 
> 
> I'm sure you object to
> 
>     1) nonintuitive operator overloading
>     2) proper use of comma expression
>     3) long lines
>     4) terse comments, not aligned with tabstops
>     5) use of = in if () statement
>     6) avoidance of newlines
>     7) avoidance of braces
>     8) individualistic programming styles
>     9) code that works so well it requires no maintenance
>        (because I have a mathematical modeling proving that
>        it works)

Ah! trick questions? Clearly 1,3,5,6,7 and 8 are objectionable, and
likely 4 as well. Now 2 is interesting, because I can't think of what
I would call a 'proper' use of the comma operator, and then for 9,
where are your proof rules for C? I'm actually interested in the
possibility of proofs of correctness in C, but so far I have not found
rules for more than a restricted subset. Perhaps you can enlighten me?

L
i
n
e
s

a
p
p
e
n
d
e
d


Later,
Andrew Mullhaupt

sullivan@aqdata.uucp (Michael T. Sullivan) (11/30/89)

From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
> 
> ...I can't think of what I would call a 'proper' use of the comma operator...

while (c = getchar(), c != EOF)
{
	...
}

I posted this instead of mailing it to see what, if any, reaction it got.
I'm always interested in coding style.
-- 
Michael Sullivan          uunet!jarthur.uucp!aqdata!sullivan
aQdata, Inc.              aqdata!sullivan@jarthur.claremont.edu
San Dimas, CA

gaynor@busboys.rutgers.edu (Silver) (11/30/89)

jeffa@hpmwtd.hp.com writes:
> I'm sure you object to
>
>   1) nonintuitive operator overloading

Agreed.  Strict adherence to a standardized naming scheme should be observed.

>   2) proper use of comma expression

Um, do you not mean "abuse of the comma expression"?  The comma has its uses
outside of function calls, like in conditional expressions and loop controls.

>   3) long lines

Here's where I disagree with the conventional idea of the cost of whitespace.
Although inexpensive, whitespace is NOT free.  Like all other facets of a
programming language, it can be (and, in my opinion, is often) abused.  The
historical precedent is to generally devoting an entire line to each single
relatively `atomic' programming construct.  However, I feel a line should
express a single idea or concept, as opposed to a single atomic programming
construct.  I don't see anything wrong with long lines as long as they can be
read and understood without strain (often achieved with extra in-line white).
In fact, I think the advantages outweigh historical precedence here.  It's very
convenient to be able to examine a non-trivial portion of code without
constantly needing to scroll/flip pages.  Gives a wholistic,
you-know-where-you-stand feeling.  Note that I am not advocating unindented
code, one must be wary of run-on lines just like in prose, and other abuses.

>   4) terse comments, not aligned with tabstops

Let's just leave it at "non-aligned", ok?  I'm not fond of tabs at all, and
never, ever use them except where *required* (e.g., some versions of make(1)).
(GNU Emacs users, consult the variable indent-tabs-mode.)

>   5) use of = in if () statement

I haven't fully made up my mind about this one, but I tend to agree, solely
because of the (what I consider) poor choice of equality and assignment
operator symbols in C.  These are the words of someone who prefers <- for
assignment and = for testing equality.  (There's no need to start yet another
war over this, is there?  Good.)

>   6) avoidance of newlines

Agreed, tempered with 3 above.  One thing I will note is that I hate to see an
entire line devoted to a single damned brace - what a gawd-awful waste of
visual space!  Yes, I embed them; as my code is consistently block-formatted,
there's no need for their emphasis.  Because editors that are very smart about
parenthetical constructs are readily available, I very rarely have mismatches.

>   7) avoidance of braces

No strong opinion either way.  I use 'em as I need them, or when their absence
creates visual non-uniformities (e.g., I usually either bracify both clauses of
an if or neither.)

>   8) individualistic programming styles

Here's where I lose big-time.  Non-lispers tell me they hate my C coding style.

>   9) code that works so well it requires no maintenance
>      (because I have a mathematical modeling proving that
>      it works)

This is in jest, right?

Ok, so let the flames begin!

Regards, [Ag] gaynor@topaz.rutgers.edu

peter@ficc.uu.net (Peter da Silva) (12/01/89)

From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
> ...I can't think of what I would call a 'proper' use of the comma operator...

for(i = 0, j = limit; i < j; i++, j--)
-- 
`-_-' Peter da Silva <peter@ficc.uu.net> <peter@sugar.lonestar.org>.
 'U`  --------------  +1 713 274 5180.
"The basic notion underlying USENET is the flame."
	-- Chuq Von Rospach, chuq@Apple.COM 

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/01/89)

In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
>> ...I can't think of what I would call a 'proper' use of the comma operator...

Mostly it finds use within fancy macros.

>while (c = getchar(), c != EOF)

The standard C idiom for this is
	while ( (c = getchar()) != EOF )
and experienced C programmers are likely to read the standard idiom
with greater facility than your proposed use of a comma operator for this.

grogers@sushi.uucp (Geoffrey Rogers) (12/01/89)

In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
>while (c = getchar(), c != EOF)
>{
>	...
>}
>
>I posted this instead of mailing it to see what, if any, reaction it got.
>I'm always interested in coding style.

In this case I would write the above as:

while ((c = getchar()) != EOF)
{
	...
}

IHMO this is much clearer then the above. In general the only places
I have found to use the comma operator is either in for-statements,
macros and maybe within expressions of ? : expression.

Geoffrey C. Rogers			"Whose brain did you get?"
grogers@convex.com			"Abbie Normal!"
{sun,uunet,uiucdcs}!convex!grogers

mark@jhereg.Minnetech.MN.ORG (Mark H. Colburn) (12/01/89)

In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
>> 
>> ...I can't think of what I would call a 'proper' use of the comma operator...
>
>while (c = getchar(), c != EOF)
>{
>	...
>}
>
>I posted this instead of mailing it to see what, if any, reaction it got.
>I'm always interested in coding style.

I agree with Henry.  There are few "proper" uses of a comma operator.
The comma operator, since it is vastly underused tends to confuse most
programmer, even competent ones.  Besides, there are more intuitive ways to
write most code which would require a comma.

The code above could be written as 

	while (c = getchar && c  != EOF) { 
	    ... 
	}

Which most programmers would find "more intuitive" than the comma seperated
one.


-- 
Mark H. Colburn                       mark@Minnetech.MN.ORG
Open Systems Architects, Inc.

barmar@think.com (12/02/89)

I hope you're prepared for a flood of followups (I know *I've* gotten them
when I've goofed like this)....

In article <427@jhereg.Minnetech.MN.ORG> mark@jhereg.minnetech.mn.org (Mark H. Colburn) writes:
>The code above could be written as 
>	while (c = getchar && c  != EOF) { 
>Which most programmers would find "more intuitive" than the comma seperated
>one.

Except, of course, that it is *not* equivalent (and I'm ignoring the
missing parentheses after "getchar").  In the comma-separated version the
loop only ends when getchar() returns EOF.  Your version terminates the
loop when getchar() returns either 0 (e.g. if the user types Control-@) or
EOF.
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

bader+@andrew.cmu.edu (Miles Bader) (12/02/89)

mark@jhereg.Minnetech.MN.ORG (Mark H. Colburn) writes:
> The code above could be written as 
> 
>         while (c = getchar && c  != EOF) { 
>             ... 
>         }
> 
> Which most programmers would find "more intuitive" than the comma seperated
> one.

But it doesn't work when c=='\000'!

jeffa@hpmwtd.HP.COM (Jeff Aguilera) (12/02/89)

>>while (c = getchar(), c != EOF)

Too much annoying white space, conveying no information or structure.  Try

    while (c=getchar(), c!=EOF)

instead.  Pull atomic concepts and actions together.

>The standard C idiom for this is
>    while ( (c = getchar()) != EOF )

Gee.  I prefer the first construct.  Indeed, it is the only one I dare use, 
because it is so much clearer.  But I understand (and accept) that most 
programmers are compelled to use the K&R form, following their masters' dogma
blindly, criticizing all others.

>and experienced C programmers are likely to read the standard idiom
>with greater facility than your proposed use of a comma operator for this.

I hope an experienced programmer is capable of understanding both expressions.
His mental algorithmic model should be independent of the implementation and
its expression.  
-----
jeffa

    Mathematicians are like Frenchmen: whatever you say to them they
    translate into their own language, and forthwith it is something
    entirely different.
            -- Johann Wolfgang von Goethe

sullivan@aqdata.uucp (Michael T. Sullivan) (12/02/89)

I've been thinking about this comma stuff.  As you may remember, I posted
the example with getchar.  All the responses I've gotten and seen posted
said I should surround the getchar in parens instead.  Why?  Not because
the commas weren't proper but because "most programmers did it that way."
Is that really a good enough reason?  Most C programmers I've encountered
do not use '?:'.  Is that a good enough reason to not use it?  I think not.
Nobody said that my use was ugly, evil, a bad idea, or wrong.  Just that
most people didn't use it.  I'll just keep on using my commas, thank you.
-- 
Michael Sullivan          uunet!jarthur.uucp!aqdata!sullivan
aQdata, Inc.
San Dimas, CA

vlcek@mit-caf.MIT.EDU (Jim Vlcek) (12/02/89)

In article <427@jhereg.Minnetech.MN.ORG> mark@jhereg.minnetech.mn.org (Mark H. Colburn) writes:
>In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:

Michael Sullivan (in the aqdata reference), proposes a 'proper' use of
the comma operator:

  while (c = getchar(), c != EOF)
  {
	...
  }

To which Mark Colburn replies:
  The code above could be written as 

	while (c = getchar && c  != EOF) { 
	    ... 
	}

  Which most programmers would find "more intuitive" than the comma
  separated one.

Sorry, but most programmers would find it "wrong".  In fact, I think
most programmers would find it difficult to get the thing _more_ wrong
than this.  First, you need the parenthesis after getchar (getchar())
- that omission, however, may be a lucky one in that it would keep
this mess from even compiling.  Second, the value assigned to ``c''
will not be the desired value (the value returned by getchar()), but
instead will be the value of the expression 

getchar() && c != EOF

This, of course, screws up the comparison with EOF, which ``c'' can
never equal (unless it was so initialized) as the && operator returns
only the values 0 and 1.  That comparison is also made with the value
of ``c'' from the last iteration of the loop, as the assignment
to ``c'' takes place _after_ the comparison to EOF.  Even if you
corrected all these problems by writing

while ((c = getchar()) && c != EOF) {
}

the semantics would still be changed in that the loop would terminate
on a return from getchar() of either 0 or EOF, whereas the previous
example terminates only on EOF (Barry Margolin already pointed this
out).

What you wanted, of course, was

while ((c = getchar()) != EOF) {
}

which, I am fairly confident, is given (probably verbatim) in K&R1.

Sorry if I seem pedantic, but I was amazed at how wrong this thing
was.  Even as I was writing this posting, I kept finding more things
wrong with it - I may have even missed a few.

Of course, if I'm wrong, this posting was done by an imposter, not Jim
Vlcek.

Fuck the moon; let's get     |  Jim Vlcek (vlcek@caf.mit.edu)
the Earth straightened out.  |            (vlcek@athena.mit.edu)

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/02/89)

In article <1989Dec1.231901.17719@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>Nobody said that my use was ugly, evil, a bad idea, or wrong.  Just that
>most people didn't use it.  I'll just keep on using my commas, thank you.

This is known as "desert island programming", for obvious reasons.

tbrakitz@phoenix.Princeton.EDU (Triantaphyllos Byron Rakitzis) (12/02/89)

>>while (c = getchar(), c != EOF)
>>{
>
>The code above could be written as 
>
>	while (c = getchar && c  != EOF) { 
	
Mark H. Colburn                       mark@Minnetech.MN.ORG
Open Systems Architects, Inc.


No!! What if getchar returns the null character? Then this test fails.
The usual C syntax for the above statement is

       while ((c = getchar()) != EOF)
            {

              blah blah;


Okay?


-- 
"C Code."
	  "C Code run."
			"Run, Code, run!"
Byron Rakitzis. (tbrakitz@phoenix.princeton.edu ---- tbrakitz@pucc.bitnet)

dts@quad.uucp (David T. Sandberg) (12/02/89)

In article <1989Dec1.231901.17719@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
:said I should surround the getchar in parens instead.  Why?  Not because
:the commas weren't proper but because "most programmers did it that way."
:Is that really a good enough reason?  Most C programmers I've encountered
:do not use '?:'.  Is that a good enough reason to not use it?  I think not.

Well, that's fine, as long as you don't mind the people who have to
support your code in your wake putting a bounty on your head for
hiding little surprises like that in your programs.  Personally, I
think that writing code that is as easy and natural as possible for
other people to comprehend and maintain is more than enough of a
reason to avoid excessive usage of commas, etc. where more common
methods will do just as well.

-- 
David Sandberg             dts@quad.uucp or ..uunet!rosevax!sialis!quad!dts

mark@jhereg.Minnetech.MN.ORG (Mark H. Colburn) (12/02/89)

In article <427@jhereg.Minnetech.MN.ORG> I write:
>The code above could be written as 
>
>	while (c = getchar && c  != EOF) { 
>	    ... 
>	}

Hmmm.  Hopefully I can point out my own error before someone else does.

This will work on most interactive terminals under Unix since most tty 
drivers assume that a NUL is a pad  character but it looses on anything 
that will recognize a NUL ('\0') character as a valid character on the
input stream.  In those cases, the ',' would be the only choice if you did
not want to split the statement into to parts.



-- 
Mark H. Colburn                       mark@Minnetech.MN.ORG
Open Systems Architects, Inc.

henry@utzoo.uucp (Henry Spencer) (12/03/89)

In article <1989Dec1.231901.17719@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>... Why?  Not because
>the commas weren't proper but because "most programmers did it that way."
>Is that really a good enough reason? ...

Actually, yes.  As a professional programmer, one of my jobs is to make
my code intelligible to my successors.  Given a choice between two
otherwise-equivalent constructs, one of them likely to be familiar and
the other likely to be unfamiliar, the unfamiliar one is always going
to be harder to understand.  Doing things in odd ways without good reason
is gratuitous obstructionism, placing your ego above your responsibilities.
-- 
Mars can wait:  we've barely   |     Henry Spencer at U of Toronto Zoology
started exploring the Moon.    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

weisen@eniac.seas.upenn.edu) (Neil I. Weisenfeld ;-) (12/03/89)

I always used the comma operator for multiple initializations in a for
construct:
	for (i=0,j=0;i<10;i++,j++)
	
Neil




-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Neil Weisenfeld			Internet: weisen@eniac.seas.upenn.edu
University of Pennsylvania	USPS:	  3700 Spruce Street, Box 572
Computer Science Dept.  		  Philadelphia, PA  19104
Class of 1991 

"No matter where you go, there you are."
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

amull@Morgan.COM (Andrew P. Mullhaupt) (12/03/89)

In article <427@jhereg.Minnetech.MN.ORG>, mark@jhereg.Minnetech.MN.ORG (Mark H. Colburn) writes:
> In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
> >From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
> >> 
> >> ...I can't think of what I would call a 'proper' use of the comma operator...
- Just for the record, I said this (A.P.Mullhaupt)
> >
> >I posted this instead of mailing it to see what, if any, reaction it got.
> >I'm always interested in coding style.
> 
> I agree with Henry.  There are few "proper" uses of a comma operator.
Who's Henry? I'm not sure if you mean me or someone who agrees with
me also in this thread. Worse yet, Henry might not agree with my
fairly provocative statement.
> The comma operator, since it is vastly underused tends to confuse most
> programmer, even competent ones.

I would like to elaborate: There are no good excuses for the comma
operator because it masquerades as true concurrent assignment where
it is a poor relation of it. The thing invites you to cram all sort
of gooey side effects into for loops with increment and assignment
operators. (This is the "Damn the Correctness! Full Speed Ahead"
school of programming.) Now with real concurrent assignment, you
really can put your loop invariant maintenance in one place:

(i++ , j--)

can be replaced by the much more attractive:

(i, j) := (i + 1, j - 1)

where concurrent assignment has the usual semantics. It evaluates
the right hand side completely before making the assignments to
the left hand side. Thus the swapping of two variables is simply

(x, y) := (y, x)

let's see that with the comma operator...maybe you like

(x+=y, y=x-y, x-=y)

instead? (Just kidding. The comma operator is really pretty low
class compared to concurrent assignment.)

One of the most important aspects of programming for clarity is
to avoid the near occasion of operator precedence or side effects.
You want the flow of control to be fully represented on the page
in as consistent a manner as is possible. I am preparing a long
treatment of this issue for posting in this newsgroup but I won't
post it until it shrinks considerably, so for now I'll just divulge
my provisional title: 'For construct considered harmful in C'.

Later,
Andrew Mullhaupt
Disclaimer: Any opinions expressed above (or threatened to be
expressed) are my own, as a result of careful study of the C
language, and are not necessarily those of Morgan Stanley.

gaynor@busboys.rutgers.edu (Silver) (12/04/89)

Hey, listen.  The comma operator is pretty low on the scale of things, it
doesn't deserve all this attention.  The general consensus seems to be that
it's not a wonderful thing, but it has its limited uses.

amull@morgan.com writes:
> One of the most important aspects of programming for clarity is to avoid the
> near occasion of operator precedence or side effects.
Hear, hear!  Fortunately, we are armed with parentheses with which to defend
ourselves!

amull@morgan.com writes:
> You want the flow of control to be fully represented on the page
> in as consistent a manner as is possible.
What's a page?  Something like a window?

Regards, [Ag]

gvr@brunix (George V. Reilly) (12/04/89)

In article <3552@convex.UUCP> grogers@convex.COM (Geoffrey Rogers) writes:
< In article <1989Nov30.001947.14883@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
< >From article <547@mars.Morgan.COM>, by amull@Morgan.COM (Andrew P. Mullhaupt):
< >while (c = getchar(), c != EOF)
< >{
< >	...
< >}
< >
< >I posted this instead of mailing it to see what, if any, reaction it got.
< >I'm always interested in coding style.
< 
< In this case I would write the above as:
< 
< while ((c = getchar()) != EOF)
< {
< 	...
< }
< 
< IHMO this is much clearer then the above. In general the only places
< I have found to use the comma operator is either in for-statements,
< macros and maybe within expressions of ? : expression.

Because of the two uses of the comma as a parameter separator and as a
sequential-expression separator, you can occasionally get unexpected
results.  Consider:

#define single(list) printf list
#define double(list) printf(list)

main()
{
	single("%d %d %d", 1, 2, 3);
	double("%d %d %d", 1, 2, 3);
}

The expansion of |single()| will yield |printf("%d %d %d", 1, 2, 3)|, while
the expansion of |double()| will yield |printf(("%d %d %d", 1, 2, 3))|.
The argument to the second printf will be treated as four comma-separated
expressions which evaluate to the last expression (3), ultimately
yielding |printf(3)|, which will probably cause a segmentation fault
and a core dump.  That's what happened to me the other day, at least.

In short, while the comma operator is sometimes useful (as in the cases
indicated in the quotation above), its potential ambiguity makes it
dangerous.
------
George V. Reilly			gvr@cs.brown.edu
uunet!brunix!gvr   gvr@browncs.bitnet	Box 1910, Brown U, Prov, RI 02912

cpcahil@virtech.uucp (Conor P. Cahill) (12/04/89)

In article <22139@brunix.UUCP>, gvr@brunix (George V. Reilly) writes:
> Because of the two uses of the comma as a parameter separator and as a
> sequential-expression separator, you can occasionally get unexpected
> results.  Consider:
> 
> #define single(list) printf list
> #define double(list) printf(list)
> 
> main()
> {
> 	single("%d %d %d", 1, 2, 3);
> 	double("%d %d %d", 1, 2, 3);
> }
> 
> The expansion of |single()| will yield |printf("%d %d %d", 1, 2, 3)|, while
> the expansion of |double()| will yield |printf(("%d %d %d", 1, 2, 3))|.

This is only true if they were called as follows:

  	single(("%d %d %d", 1, 2, 3));
  	double(("%d %d %d", 1, 2, 3));

which is one of the reasons that I dislike cpp not being able to handle 
a variable number of arguments to a macro (because it forces people to 
think up this solution, or to make up different macros for different numbers 
of arguments).



-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

bill@twwells.com (T. William Wells) (12/04/89)

In article <565@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt)
[presents his subjective judgements as relevant to the discussion.]

Sorry buddy, but your judgements are not mine. Moreoever, while
some of your conclusions are valid, basing them on subjective
judgements makes them appear less valid.

For example,

	"There are no good excuses for the comma operator because
	it masquerades as true concurrent assignment where it is a
	poor relation of it."

Maybe you think that the comma operator looks like concurrent
assignment. If so, you need to work harder at disentangling your
previous experience from your C programming. Many, perhaps most,
C programmers don't ever think of concurrent assignment when
seeing the comma operator. Certainly experienced C programmers
don't. You then go on to say:

	"The thing invites you to cram all sort of gooey side
	effects into for loops with increment and assignment
	operators."

Which is true, yet since you present it as related to that
subjective statement, you *weaken* the force of the statement.

Then you say (after a gratuitous and false ad hominem):

:                         Now with real concurrent assignment, you
: really can put your loop invariant maintenance in one place:
:
: (i++ , j--)
:
: can be replaced by the much more attractive:
:
: (i, j) := (i + 1, j - 1)

Yet again we have a very subjective judgement, one which I very
much disagree with. In fact, I'd say that the latter is defective
on more than one level. Besides the extraneous characters needed
to express a much simpler idea, you have interleaved two distinct
ideas, incrementing `i' and decrementing 'j'; this sort of thing
leads to decreased understanding.

On the other hand, you describe the swap operation, written as:

: (x, y) := (y, x)

which is, indeed, a good use of the idea of concurrent assignment.
There is one operation being expressed, so there is no burden on
the reader to disentangle several ideas from the single piece of
code.

The primary error that the comma operator leads to, when used in
the for statement, is the including of things which are not part
of the control structure itself, moving the controlled statements
into the for, and thus presenting the reader with several ideas
crammed into the one statement.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

gvr@brunix (George V. Reilly) (12/04/89)

In article <22139@brunix.UUCP> gvr@panda.UUCP (George V. Reilly) [I] wrote:
: Because of the two uses of the comma as a parameter separator and as a
: sequential-expression separator, you can occasionally get unexpected
: results.  Consider:
: 
: #define single(list) printf list
: #define double(list) printf(list)
: 
: main()
: {
: 	single("%d %d %d", 1, 2, 3);
: 	double("%d %d %d", 1, 2, 3);
: }
: 
: The expansion of |single()| will yield |printf("%d %d %d", 1, 2, 3)|, while
: the expansion of |double()| will yield |printf(("%d %d %d", 1, 2, 3))|.
: The argument to the second printf will be treated as four comma-separated
: expressions which evaluate to the last expression (3), ultimately
: yielding |printf(3)|, which will probably cause a segmentation fault
: and a core dump.  That's what happened to me the other day, at least.

Oops, I goofed.  There should have been two sets of parentheses each
for the invocations of |single()| and |double()|, thus:

	single(("%d %d %d\n", 1, 2, 3));
	double(("%d %d %d\n", 1, 2, 3));

Thanks to Rich Salz for pointing out that my original posting got
argument-mismatch errors from cpp.
------
George V. Reilly			gvr@cs.brown.edu
uunet!brunix!gvr   gvr@browncs.bitnet	Box 1910, Brown U, Prov, RI 02912

amull@Morgan.COM (Andrew P. Mullhaupt) (12/05/89)

In article <1989Dec4.032918.16550@twwells.com>, bill@twwells.com (T. William Wells) writes:
> In article <565@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt)
> [presents his subjective judgements as relevant to the discussion.]

	I doubt it is possible to discuss questions of style with complete
objectivty, but I do not believe that nothing constructive can be said.

	My 'readability ethic' is perhaps evident in the analogy between
reading a newspaper and reading a program; activities which shouldn't
be as far apart as they presently seem. Journalists and newspaper
editors live and die by achieving the widest possible readability,
(as well as by advertising gimmicks...) and perhaps we might profit
by thinking about how this comes about. Try substituting the words
'C program' for 'newspaper', 'statement' for 'sentence', and
'preprocessing' for 'typesetting' in the following:

	When you read a newspaper, there's something dreadfully wrong
if your first impression is of cleverly and compactly punctuated
sentences with new and interesting typesetting. The punctuation and
typesetting are important, but only so far as they are needed to
determine meaning, and assist the human reader to correctly grasp it.


> 
> Sorry buddy, but your judgements are not mine. Moreoever, while
> some of your conclusions are valid, basing them on subjective
> judgements makes them appear less valid.
> 
> For example,
> 
> 	"There are no good excuses for the comma operator because
> 	it masquerades as true concurrent assignment where it is a
> 	poor relation of it."
> 
> Maybe you think that the comma operator looks like concurrent
> assignment. If so, you need to work harder at disentangling your
> previous experience from your C programming. Many, perhaps most,
> C programmers don't ever think of concurrent assignment when
> seeing the comma operator. Certainly experienced C programmers
> don't. 

	I don't think the standard of readability is wide enough if
only by removing 'previous experience' can we understand C programs.

	Also: I disagree. Comma clauses which occur as "re-initializations"
in for constructs are often a form of concurrent assignment. You want
to make more than one assignment in a place where a single statement
is required, because these assignments belong together. Now either
they are sequential (order dependent) in which case the comma clause
will contain side effects, or they are done essentially as concurrent
assignment. Now it really doesn't matter what the programmer thinks
when he writes the code, (most of the RISC architectures had to do away
with the RPM - 'read programmer's mind' instruction), it matters what
is written.

>        You then go on to say:
> 
> 	"The thing invites you to cram all sort of gooey side
> 	effects into for loops with increment and assignment
> 	operators."
> 
> Which is true, yet since you present it as related to that
> subjective statement, you *weaken* the force of the statement.
> 
> Then you say (after a gratuitous and false ad hominem):

I didn't mean for my sarcasm to be taken as ad hominem, and so I 
must apologise. I was trying to indicate how side effects can obscure
the real intent of a comma expression. I didn't think anyone would
seriously prefer that form.

> 
> :                         Now with real concurrent assignment, you
> : really can put your loop invariant maintenance in one place:
> :
> : (i++ , j--)
> :
> : can be replaced by the much more attractive:
> :
> : (i, j) := (i + 1, j - 1)
> 
> Yet again we have a very subjective judgement, one which I very
> much disagree with. In fact, I'd say that the latter is defective
> on more than one level. Besides the extraneous characters needed
> to express a much simpler idea, you have interleaved two distinct
> ideas, incrementing `i' and decrementing 'j'; this sort of thing
> leads to decreased understanding.
> 

Finally - the real nitty-gritty:

	You can disagree all you want, but there is a reason that the
concurrent assignment is preferable to the comma clause, and it
has nothing to do with counting characters. It has to do with 
the putative role of the given expression as establishing a loop
invariant.

	When you establish an invariant expression, you would like to
do it all in one place, and all at the same time. Since concurrent
assignment evaluates the right hand side before making any of the
assignments, you are assured that there is no 'sequence point' where
half of your invariant has been fixed (and the other half broken)
and you are relieved of the burden of worrying about what order
the assignments are done in. Not having control of this order stops
all but the most reckless programmers from putting in side effects,
function evaluations, or anything else sticky in the expression. 


Later,
Andrew Mullhaupt

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/05/89)

In article <565@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
-I would like to elaborate: There are no good excuses for the comma
-operator because it masquerades as true concurrent assignment where
-it is a poor relation of it.

No such thing.  C's comma operator is specifically sequential,
not even remotely concurrent.

It has uses primarily in macros, occasionally in conditionals.

-... I am preparing a long
-treatment of this issue for posting in this newsgroup but I won't
-post it until it shrinks considerably, so for now I'll just divulge
-my provisional title: 'For construct considered harmful in C'.

How about entitling it "Pascal-think inappropriate for C".

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/05/89)

In article <680014@hpmwjaa.HP.COM> jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
->>while (c = getchar(), c != EOF)
-Too much annoying white space, conveying no information or structure.  Try
-    while (c=getchar(), c!=EOF)
-instead.  Pull atomic concepts and actions together.

I think most experienced programmers would prefer white space around
assignment operators.  I prefer whitespace around any infix binary
operator.  This is not terribly important anyway.

->The standard C idiom for this is
->    while ( (c = getchar()) != EOF )
-Gee.  I prefer the first construct.  Indeed, it is the only one I dare use, 
-because it is so much clearer.

Clarity must be in the eye of the beholder, because many programmers
find the standard idiom much clearer: "get a character into`c' and test
it against EOF".  With the form you prefer, one has to mentally connect
the two occurrences of `c' and appreciate that their contents are
related.  That connection is automatic to the experienced user of the
second form.

-But I understand (and accept) that most programmers are compelled to
-use the K&R form, following their masters' dogma blindly, criticizing
-all others.

You don't understand shit.

henry@utzoo.uucp (Henry Spencer) (12/06/89)

In article <680014@hpmwjaa.HP.COM> jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
>>and experienced C programmers are likely to read the standard idiom
>>with greater facility than your proposed use of a comma operator for this.
>
>I hope an experienced programmer is capable of understanding both expressions.
>His mental algorithmic model should be independent of the implementation and
>its expression.  

Of course he would be capable of understanding both.  But *read* the words
you are replying to:  "with greater facility".  He will understand both,
but will find it easier, less distracting, and more conducive to productive
work to read the familiar idiom.  The objective is maximum clarity, not some
bare-minimum standard of legibility.
-- 
Mars can wait:  we've barely   |     Henry Spencer at U of Toronto Zoology
started exploring the Moon.    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

jharkins@sagpd1.UUCP (Jim Harkins) (12/06/89)

In article <680014@hpmwjaa.HP.COM> jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
>Gee.  I prefer the first construct.  Indeed, it is the only one I dare use, 
>because it is so much clearer.  But I understand (and accept) that most 
>programmers are compelled to use the K&R form, following their masters' dogma
>blindly, criticizing all others.

Language english use I although but standard not.  Easier much more understand
it be, realize although I 90% world of the idiom different use.  Masters'
dogma rot that all and.

jim
"May you always have the strength to enjoy your weaknesses."

jmann@bigbootay (Jim Mann) (12/06/89)

But "most programmers don't do it" IS a good reason to avoid a 
contruct if other programmers have to maintain your code. 

cik@l.cc.purdue.edu (Herman Rubin) (12/06/89)

In article <447@lectroid.sw.stratus.com>, jmann@bigbootay (Jim Mann) writes:
> But "most programmers don't do it" IS a good reason to avoid a 
> contruct if other programmers have to maintain your code. 

Just as "most teachers can't teach it" is a good reason not to include
important material in a course?
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)

bill@twwells.com (T. William Wells) (12/06/89)

In article <551@sagpd1.UUCP> jharkins@sagpd1.UUCP (Jim Harkins) writes:
: In article <680014@hpmwjaa.HP.COM> jeffa@hpmwtd.HP.COM (Jeff Aguilera) writes:
: >Gee.  I prefer the first construct.  Indeed, it is the only one I dare use,
: >because it is so much clearer.  But I understand (and accept) that most
: >programmers are compelled to use the K&R form, following their masters' dogma
: >blindly, criticizing all others.
:
: Language english use I although but standard not.  Easier much more understand
: it be, realize although I 90% world of the idiom different use.  Masters'
: dogma rot that all and.

Well said. :-)

Although maybe you should have put in this comma.... :-)

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

dmocsny@uceng.UC.EDU (daniel mocsny) (12/07/89)

In article <1765@l.cc.purdue.edu>, cik@l.cc.purdue.edu (Herman Rubin) writes:
> In article <447@lectroid.sw.stratus.com>, jmann@bigbootay (Jim Mann) writes:
> > But "most programmers don't do it" IS a good reason to avoid a 
> > contruct if other programmers have to maintain your code. 
> 
> Just as "most teachers can't teach it" is a good reason not to include
> important material in a course?

This is an example of everlasting conflict between Universality and
Virtuosity. When a single human is able to produce a completely
self-contained intellectual construct, then that human enjoys great
latitude for virtuosity. For example, great artists, musicians,
surgeons, athletes, and yes, teachers, are often mostly free to
exercise their abilities to their limits. The major drawback to
virtuosity, of course, is that it rarely out-lives whoever happens
to possess it.

When a single human is unable to deliver a completely self-contained
work, then that human must necessarily compromise her/his creative
freedom to satisfy the needs of all the other people who will
subsequently add value to it. This is rarely truer than with computer
software, where virtually every code of widespread consequence must be
readily understandable to many people. However, I believe the creative
programmer need not find this excessively burdensome. Rather, it
should be just another creative challenge---how to write code that not
only performs efficiently, but also illumines the human reader. A
masterpiece of code should both run well and have its meaning
virtually jump out and grab the next guy.

Nonetheless, the needs of computers and people are wildly different.
Probably only a few elite programmers can simultaneously realize
efficiency and clarity. A possibly more sensible approach would be to
build tools that translate machine-efficient code into something
easier for humans to understand. A documentation compiler, so to
speak. For example, a smart pager program could display someone
else's code to you, while other windows verbosely expanding cryptic
constructs into something readable, showing the original author's
comments, etc. While we're at it, we could throw in hypertext-style
references to applicable literature references, code-fragment
animators, etc.

Dan Mocsny
dmocsny@uceng.uc.edu

chip@ateng.com (Chip Salzenberg) (12/08/89)

According to jeffa@hpmwtd.HP.COM (Jeff Aguilera):
>I understand (and accept) that most programmers are compelled to use the K&R
>form, following their masters' dogma blindly, criticizing all others.

Mr. Aguilera understands nothing. "Criticizing all others," indeed!  A
certain phrase mentioning pots and kettles comes to mind.

A construct's being quickly identifiable by most C programmers makes that
thing immediately preferable to an equivalent but less common construct.
And if there's one book a C programmer has almost certainly read, it's K&R.

The general rule I adhere to most strictly is:  "Repetition is evil."
For example, "i = i + 1" is inherently harder to read than "i++", since the
former requires the identification of two variable names (albeit identical
ones) whereas the latter only contains one name.  The expression
"c=getchar(), c!=EOF" is harder to read than "(c = getchar()) != EOF" for
the same reason.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
	  "The Usenet, in a very real sense, does not exist."

bill@twwells.com (T. William Wells) (12/08/89)

In article <574@mars.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
: In article <1989Dec4.032918.16550@twwells.com>, bill@twwells.com (T. William Wells) writes:
: > In article <565@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt)
: > [presents his subjective judgements as relevant to the discussion.]
:
:       My 'readability ethic' is perhaps evident in the analogy between
: reading a newspaper and reading a program; activities which shouldn't
: be as far apart as they presently seem. Journalists and newspaper
: editors live and die by achieving the widest possible readability,
: (as well as by advertising gimmicks...) and perhaps we might profit
: by thinking about how this comes about. Try substituting the words
: 'C program' for 'newspaper', 'statement' for 'sentence', and
: 'preprocessing' for 'typesetting' in the following:

There is a fundamental flaw in the analogy. Newspapers and other
publications today, unfortunately, tend to try to widen their
readership by pandering to the semi-illiterates in their
potential audience. Computer programs should try to widen their
readership by being valuable to those who can know how to use
them. These lead to radically different views on what makes the
thing more readable.

:                                         Try substituting the words
: 'C program' for 'newspaper', 'statement' for 'sentence', and
: 'preprocessing' for 'typesetting' in the following:
:
:       When you read a newspaper, there's something dreadfully wrong
: if your first impression is of cleverly and compactly punctuated
: sentences with new and interesting typesetting. The punctuation and
: typesetting are important, but only so far as they are needed to
: determine meaning, and assist the human reader to correctly grasp it.

But I certainly won't disagree with the above.

: > Sorry buddy, but your judgements are not mine. Moreoever, while
: > some of your conclusions are valid, basing them on subjective
: > judgements makes them appear less valid.
: >
: > For example,
: >
: >     "There are no good excuses for the comma operator because
: >     it masquerades as true concurrent assignment where it is a
: >     poor relation of it."
: >
: > Maybe you think that the comma operator looks like concurrent
: > assignment. If so, you need to work harder at disentangling your
: > previous experience from your C programming. Many, perhaps most,
: > C programmers don't ever think of concurrent assignment when
: > seeing the comma operator. Certainly experienced C programmers
: > don't.
:
:       I don't think the standard of readability is wide enough if
: only by removing 'previous experience' can we understand C programs.

Eh? I didn't say "remove previous experience". The point I was
making is that C programming is its own unique thing. While it
has much in common with some other activities, it is also
different in many ways. It is a mistake to drag in concepts from
other activities that are not applicable to C programming.

C can not be profitably made to look like other languages by
cosmetic means. Nor by applying irrelevant concepts in your
understanding of it. Doing the latter will just lead to confusion.

:       Also: I disagree. Comma clauses which occur as "re-initializations"
: in for constructs are often a form of concurrent assignment.

What? They are nothing of the sort. It is true that some compilers
can take advantage of the fact that certain uses of the comma
operator can, though there is an implied sequence, be done
concurrently. But there is nothing special about the comma
operator in that respect.

++i, ++j is *not* concurrent. It is sequential. It may happen that
the machine can do them concurrently. If so, it has to act *as if*
they were done sequentially. But the fact that they might be
processed concurrently does not change the fact that the
expression is conceptually sequential. To think of it as
concurrent is an error.

:             Now it really doesn't matter what the programmer thinks
: when he writes the code, (most of the RISC architectures had to do away
: with the RPM - 'read programmer's mind' instruction), it matters what
: is written.

And what is written IS SEQUENTIAL.

: > :                         Now with real concurrent assignment, you
: > : really can put your loop invariant maintenance in one place:
: > :
: > : (i++ , j--)
: > :
: > : can be replaced by the much more attractive:
: > :
: > : (i, j) := (i + 1, j - 1)
: >
: > Yet again we have a very subjective judgement, one which I very
: > much disagree with. In fact, I'd say that the latter is defective
: > on more than one level. Besides the extraneous characters needed
: > to express a much simpler idea, you have interleaved two distinct
: > ideas, incrementing `i' and decrementing 'j'; this sort of thing
: > leads to decreased understanding.
:
: Finally - the real nitty-gritty:
:
:       You can disagree all you want, but there is a reason that the
: concurrent assignment is preferable to the comma clause, and it
: has nothing to do with counting characters. It has to do with
: the putative role of the given expression as establishing a loop
: invariant.

But the notion that taking ++i, --j, a simple, easy to understand
expression, and complexifying it into (i, j) := (i + 1, j - 1),
in the interests of "put[ting] your loop invariant maintenance in
one place", is indefensible. It is already *in* one place, the
third expression of the for statement.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

richard@aiai.ed.ac.uk (Richard Tobin) (12/08/89)

In article <11743@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:

[On the subject of  while (c=getchar(), c!=EOF)]

>With the form you prefer, one has to mentally connect the two occurrences
>of `c' and appreciate that their contents are related.

If you can't do that, then you're not going to get far understanding
*any* program.  The (alleged) added effort in understanding this construct
is surely miniscule in the context of understanding a whole program.

I would have thought that it's common enough to be regarded as a
standard idiom itself.  At least, everyone who reads this newsgroup
should by now be quite sufficiently familiar with it!

-- Richard

-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

ge@kunivv1.sci.kun.nl (Ge' Weijers) (12/08/89)

gwyn@smoke.BRL.MIL (Doug Gwyn) writes:

>In article <1989Dec1.231901.17719@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
>>Nobody said that my use was ugly, evil, a bad idea, or wrong.  Just that
>>most people didn't use it.  I'll just keep on using my commas, thank you.

>This is known as "desert island programming", for obvious reasons.

What this world needs is a very-much-improved version of SCCS or the like,
that shows each programmer the same source in his own programming style.

Conversions to be implemented:

- indentation styles
- (ab)use of the comma operator
- ......... (your favorite pet peeve here)

Everyone could sit on a desert island, under his own fig tree,
and no comma operator shall make him afraid. :-)

De gustibus non disputandum est.

Ge'
Ge' Weijers                                    Internet/UUCP: ge@cs.kun.nl
Faculty of Mathematics and Computer Science,   (uunet.uu.net!cs.kun.nl!ge)
University of Nijmegen, Toernooiveld 1         
6525 ED Nijmegen, the Netherlands              tel. +3180612483 (UTC-2)

ge@kunivv1.sci.kun.nl (Ge' Weijers) (12/08/89)

amull@Morgan.COM (Andrew P. Mullhaupt) writes:
>I would like to elaborate: There are no good excuses for the comma
>operator because it masquerades as true concurrent assignment where
>it is a poor relation of it. The thing invites you to cram all sort
>of gooey side effects into for loops with increment and assignment
>operators. (This is the "Damn the Correctness! Full Speed Ahead"
>school of programming.) Now with real concurrent assignment, you
>really can put your loop invariant maintenance in one place:

>(i++ , j--)

>can be replaced by the much more attractive:

>(i, j) := (i + 1, j - 1)

The comma operator has nothing to do at all with the concurrent assignment.
The left operand is evaluated only for its side-effect. It is most useful
when implementing macros that need to do multiple things. (look at the
expansion of getchar() to see my point). The concurrent assignment is
very useful, as it lets the compiler worry about difficult constructs,
in stead of you. Example: the pointer rotation.
(p is a pointer to a binary tree node with left and right fields)

	(p, p->right, p->right->left) := (p->right, p->right->left, p);

Try this in C. The above is more elegant.
The obvious way:

	tmp1 = p->right; tmp2 = p->right->left; tmp3 = p;
	p = tmp1; p->right = tmp2; p->right->left = tmp3;

Now what did I do wrong :-)

It makes writing down things like that much easier, the compiler worries
about keeping things in temporaries, figuring out optimal ordering etc.
Useful, ain't it?

(forgive my ramblings, but I though Andrew Mulhaupt's example was a little
oversimplified. concurrent assignment more useful than that. C is definitely
not the last word in programming languages, whether ANSI, ++ or whatever.)

Ge' Weijers
Ge' Weijers                                    Internet/UUCP: ge@cs.kun.nl
Faculty of Mathematics and Computer Science,   (uunet.uu.net!cs.kun.nl!ge)
University of Nijmegen, Toernooiveld 1         
6525 ED Nijmegen, the Netherlands              tel. +3180612483 (UTC-2)

ge@kunivv1.sci.kun.nl (Ge' Weijers) (12/08/89)

cik@l.cc.purdue.edu (Herman Rubin) writes:

>In article <447@lectroid.sw.stratus.com>, jmann@bigbootay (Jim Mann) writes:
>> But "most programmers don't do it" IS a good reason to avoid a 
>> contruct if other programmers have to maintain your code. 

>Just as "most teachers can't teach it" is a good reason not to include
>important material in a course?

And 'most countries are not democracies'. 

Ge' Weijers


Ge' Weijers                                    Internet/UUCP: ge@cs.kun.nl
Faculty of Mathematics and Computer Science,   (uunet.uu.net!cs.kun.nl!ge)
University of Nijmegen, Toernooiveld 1         
6525 ED Nijmegen, the Netherlands              tel. +3180612483 (UTC-2)

dts@quad.uucp (David T. Sandberg) (12/10/89)

In article <1437@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
:
:[On the subject of  while (c=getchar(), c!=EOF)]
:
:I would have thought that it's common enough to be regarded as a
:standard idiom itself.  At least, everyone who reads this newsgroup
:should by now be quite sufficiently familiar with it!

Sure.  And we've also become familiar with the effects of interweaving
loops and case labels, but that doesn't make it a good idea.

In any event, I've yet to see  while (c=getchar(), c!=EOF)  used in
any real world code.  Just lucky, I guess.  ;')

-- 
David Sandberg             dts@quad.uucp or ..uunet!rosevax!sialis!quad!dts
"What's the difference??"

henry@utzoo.uucp (Henry Spencer) (12/10/89)

In article <570@kunivv1.sci.kun.nl> ge@kunivv1.sci.kun.nl (Ge' Weijers) writes:
>What this world needs is a very-much-improved version of SCCS or the like,
>that shows each programmer the same source in his own programming style.

Unfortunately, paragraphers cannot read minds.  Automatic reparagraphing
is *not* a substitute for careful work in a standard style by the original
programmer.
-- 
1755 EST, Dec 14, 1972:  human |     Henry Spencer at U of Toronto Zoology
exploration of space terminates| uunet!attcan!utzoo!henry henry@zoo.toronto.edu

tps@chem.ucsd.edu (Tom Stockfisch) (12/10/89)

In article <257E97F4.24962@ateng.com> chip@ateng.com (Chip Salzenberg) writes:
>According to jeffa@hpmwtd.HP.COM (Jeff Aguilera):
>>I understand (and accept) that most programmers are compelled to use the K&R
>>form, following their masters' dogma blindly, criticizing all others.

>A construct's being quickly identifiable by most C programmers makes that
>thing immediately preferable to an equivalent but less common construct.
>And if there's one book a C programmer has almost certainly read, it's K&R.

I think the point here is that style evolves, and wouldn't if people never
strayed from K&R.  For instance, what if I justified my use of
	
	while (*s++ = *t++)
		;

by quoting K&R (I p. 101, II p. 106)?

>The general rule I adhere to most strictly is:  "Repetition is evil."
>...  The expression
>"c=getchar(), c!=EOF" is harder to read than "(c = getchar()) != EOF" for
>the same reason.

Perhaps it is just because I have never learned lisp, but what *I* find
most difficult to read are multiple sets of parentheses.  Even though
I have never used Jeff's form before in a "while" construct, I still found
it easier to read than the "standard" notation.  The repetition is
just one character here ("c"), and very close by.  Am I the only person
who is slowed down by lots of parentheses?

Just in case what I have said so far doesn't generate any flames, I'll
offer what I would write for this case:

	for ( c = getchar(); c != EOF; c = getchar() )
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

amull@Morgan.COM (Andrew P. Mullhaupt) (12/11/89)

In article <257E97F4.24962@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
> The general rule I adhere to most strictly is:  "Repetition is evil."
> For example, "i = i + 1" is inherently harder to read than "i++", since the
> former requires the identification of two variable names (albeit identical
> ones) whereas the latter only contains one name.  The expression
> "c=getchar(), c!=EOF" is harder to read than "(c = getchar()) != EOF" for
> the same reason.

Isn't it possible that in some places repetition can increase
readability? I don't really object to your conclusion here, but
in those cases where avoiding repetition to the utmost requires
sharp use of precendence rules, and only to avoid repetition, I
take issue. I think that operator precedence often breaks up the
ability to read code from one end of the line to the other, especially
when casts are involved, and this takes work to disentangle. I'd
rather break some expressions into more than one part just to keep
the lid on the complexity, even if I need to see the same thing twice
in a row. The elimination of all redundancy, which seems the 
logical extrapolation of your strict adherence to your rule, is
not likely to help me read the code.

Later,
Andrew Mullhaupt

scm@dlcq15.datlog.co.uk (Steve Mawer) (12/11/89)

In article <1989Dec4.032918.16550@twwells.com> bill@twwells.com (T. William Wells) writes:
>The primary error that the comma operator leads to, when used in
>the for statement, is the including of things which are not part
>of the control structure itself, moving the controlled statements
>into the for, and thus presenting the reader with several ideas
>crammed into the one statement.

You mean it's *not* a sign of a poor C programmer to put more than a
single semicolon in the body of a for loop?  :-)

--
Steve C. Mawer        <scm@datlog.co.uk> or < {backbone}!ukc!datlog!scm >
                       Voice:  +44 1 863 0383 (x2153)

chip@ateng.com (Chip Salzenberg) (12/12/89)

According to tps@chem.ucsd.edu (Tom Stockfisch):
>I think the point here is that style evolves, and wouldn't if people never
>strayed from K&R.  For instance, what if I justified my use of
>	
>	while (*s++ = *t++)
>		;
>
>by quoting K&R (I p. 101, II p. 106)?

You're right.  Style evolves.  However, stylistic evolution based on common
errors is different from arbitrary changes based on personal preference.
Your example contains an assignment used as a boolean value, which is a
questionable practice at best, due to the possibility of "="/"==" error.
So the alternative "while ((*s++ = *t++) != 0) {}" is demonstrably better.

On the other hand, I'd say that "c=getchar(), c!=EOF" provides little, if
any, benefit over "(c = getchar()) != EOF".  It has the advantage of fewer
parentheses, true, but it has the disadvantage of multiple references to
the single variable.  In my opinion, it's not a worthwhile tradeoff.

>Perhaps it is just because I have never learned lisp, but what *I* find
>most difficult to read are multiple sets of parentheses.

I hate LISP, aka Lots of Irritating Stupid Parentheses.  But we're not
talking brain surgery here.  My getchar() expression nests only one level
deeper than "c=getchar(), c!=EOF".  I usually parse it visually this way:

	if ((c = getchar()) != EOF)
	    ^       open^ ^       ^close
	   two open      two close

>Am I the only person who is slowed down by lots of parentheses?

Idioms are easy to parse once you're used to them.  Use tricks, as above.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
	  "The Usenet, in a very real sense, does not exist."

evil@arcturus.UUCP (Wade Guthrie) (12/12/89)

In article <565@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
>I would like to elaborate: There are no good excuses for the comma
>operator . . .

and gwyn@smoke.BRL.MIL (Doug Gwyn) responds:
>. . .It has uses primarily in macros, occasionally in conditionals.

I always thought that an interesting use for the comma was in a for
loop when one wanted, say, to create the identity matrix:

	float	array[SIZE][SIZE];
	int	i,j;

	/* initialize the whole thing to zero, then to this: */
	for(i=0,j=0; i<SIZE; i++, j++)
		array[i][j] = 0;

Although, I guess, you don't need two indices for this.


Wade Guthrie
evil@arcturus.UUCP
Rockwell International
Anaheim, CA

(Rockwell doesn't necessarily believe / stand by what I'm saying; how could
they when *I* don't even know what I'm talking about???)

scm@datlog.co.uk ( Steve Mawer ) (12/12/89)

In article <1989Dec4.032918.16550@twwells.com> bill@twwells.com (T. William Wells) writes:
>The primary error that the comma operator leads to, when used in
>the for statement, is the including of things which are not part
>of the control structure itself, moving the controlled statements
>into the for, and thus presenting the reader with several ideas
>crammed into the one statement.

You mean it's *not* the sign of a poor programmer to have more than a
semicolon in the body of a for loop?  :-)

-- 
Steve C. Mawer        <scm@datlog.co.uk> or < {backbone}!ukc!datlog!scm >
                       Voice:  +44 1 863 0383 (x2153)

chip@ateng.com (Chip Salzenberg) (12/13/89)

According to amull@Morgan.COM (Andrew P. Mullhaupt):
>According to chip@ateng.com (Chip Salzenberg):
>> The general rule I adhere to most strictly is:  "Repetition is evil."
>> The expression "c=getchar(), c!=EOF" is harder to read than
>> "(c = getchar()) != EOF" for [this] reason.
>
>Isn't it possible that in some places repetition can increase
>readability?

Of course.  Any style rule, taken to the extreme, can be counterproductive.
But elimination of redundancy leads automatically to several good
programming practices, especially factoring.

True, readability is only one issue.  But small-scale and large-scale
readability are sometimes at odds.  For example, if you write a program that
consists entirely of simple, understandable modules, that's fine; but if the
functions of the program are factored badly enough, the source will be too
big to understand, and will therefore be unreadable on the large scale.

I think that the best measure of readability is not lines of code per unit
time, but percentage of program per unit time.  If a routine takes ten
minutes to understand, that's bad; but if that routine is one tenth of the
program, things are looking up.

>I'd rather break some expressions into more than one part just to keep
>the lid on the complexity, even if I need to see the same thing twice
>in a row.

Actually, the creation of temporary variables is a classic way to eliminate
repetition in program code.  I constantly use them that way myself.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
	  "The Usenet, in a very real sense, does not exist."

mike@nixba.UUCP (Mike Lyons) (12/15/89)

I once taught a C seminar for Philips, and in their house "style manual" for
C the use of the comma operator was absolutely forbidden.  But then, they also
had a full set of "make-the-C-language-look-like-Pascal" macros in the 
mandatory include file "philips.h." Sheesh!!

Peace,
  Mike
-- 
Michael D. Lyons / Nixdorf Computer AG / phone: +49 911 6415 609
Donaustrasse 36 :: D-8500 Nuernberg 60 :: Federal Republic of Germany
EUNET: mike@nixba.uucp   NERV: lyons.nue   OTHERWISE: ...unido!nixba!mike
I'd change the world for the better...if I could get my hands on the source code

exspes@gdr.bath.ac.uk (P E Smee) (12/18/89)

In article <490@nixba.UUCP> mike@nixba.UUCP (Mike Lyons) writes:
>I once taught a C seminar for Philips, and in their house "style manual" for
>C the use of the comma operator was absolutely forbidden.

I have a pathlogical dislike for the comma operator, because its most
common use seems to be to allow overloading of too many unrelated concepts
into one source line, in a sort of 'Gosh, amn't I clever' coding style.
Banning it altogether is probably excessive, because I think there are
occasions when it helps make things clearer or more efficient.  I do wish,
though, that someone could put a heuristic into the compiler so that it
would be rejected if it is being used because it is 'flash' rather than
because it wins something in the context. :-)

-- 
Paul Smee, Univ of Bristol Comp Centre, Bristol BS8 1TW, Tel +44 272 303132
 Smee@bristol.ac.uk  :-)  (..!uunet!ukc!gdr.bath.ac.uk!exspes if you MUST)

bright@Data-IO.COM (Walter Bright) (12/21/89)

<I do wish,
<though, that someone could put a heuristic into the compiler so that it
<would be rejected if it is being used because it is 'flash' rather than
<because it wins something in the context. :-)

I'd put a compiler that did that in the category of 'smart-ass' rather
than 'smart'. :-) :-)

jonathan.forbes@canremote.uucp (JONATHAN FORBES) (12/21/89)

Even so, writing C code that way can still be hard to read.  The way I 
write all of my C code is:
 
if (something)
   {
      SomethingElse();
   }
 
for (;;)
   {
      ...
   }
 
It's much much easier this way, to see what matches up with what.
 
---
 * Via ProDoor 3.1R