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
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
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.
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
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
henry@utzoo.uucp (Henry Spencer) (04/27/89)
In article <2495@bucsb.UUCP> crewman@bucsb.bu.edu writes: >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? We are not bending over backwards to make our programs easier to read for amateurs; we are bending over backwards to make them easier to read for our fellow professionals. We are not trying to meet some minimum standard of readability, and indulging our little egos beyond that; we are trying to make the stuff AS CLEAR AS POSSIBLE even if it hurts. >C is designed to be a low-level language... Opinions vary on this. How do you write "*p++ = *q++" in Fortran? Which is the higher level language, based on this comparison? (Or any comparison, apart from the marginal issue of complex numbers.) >...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. As C programmers, we have the tools to make powerful programs utterly unreadable if we make the slightest effort in that direction. Making them readable, on the other end, takes significant work and considerable restraint. -- 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.
pjh@mccc.UUCP (Pete Holsberg) (04/29/89)
In article <1989Apr26.215113.10807@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
=As C programmers, we have the tools to make powerful programs utterly
=unreadable if we make the slightest effort in that direction. Making them
=readable, on the other end, takes significant work and considerable restraint.
=--
Here, here! After spending a very frustrating day on a "2-3 hour job",
I want to say: write good documentation, too. Write an overview of the
program, and each major function. If you print the source code, put
tabs on the pages and include a table of contents and maybe a "cflow"
output. My client "wasted" some bucks today because of all the reading
and paper-shuffling I had to do.
Pete
--
Pete Holsberg UUCP: {...!rutgers!}princeton!mccc!pjh
Mercer College CompuServe: 70240,334
1200 Old Trenton Road GEnie: PJHOLSBERG
Trenton, NJ 08690 Voice: 1-609-586-4800
Kemp@DOCKMASTER.NCSC.MIL (04/30/89)
>>C is designed to be a low-level language... Henry Spencer replies: > Opinions vary on this. How do you write "*p++ = *q++" in Fortran? > Which is the higher level language, based on this comparison? (or > any comparison, apart from the marginal issue of complex numbers.) Much as I fear disagreeing with Henry, I have to respond to this :-) In Fortran, one writes "p(i) = q(i)", at least inside a loop, which is where such a construct is normally found. This is "higher level" in that it is more like the mathematical notion of "copy array q to array p" than the machine level description "fetch data pointed to by q, increment q, copy to location pointed to by p, increment p". While opinions may (and do) vary on everything, some opinions correspond to reality more closely than others. If you define "high level" as meaning "a higher level of data abstraction" then Fortran is clearly higher level than C for the types of data it was designed to handle (numbers, arrays, strings, and structures thereof). If you equate higher level with "fewer characters needed to define an algorithm", then opinions may vary. For anything involving explicit pointer manipulation (trees, queues, etc) Fortran is entirely unsuitable, and C is thus "higher level". ----------------------- Arrays: Although C has an array notation, it is not used very effectively. I don't know of any C compilers that do array bounds checking (which does not mean that none exist, but they are not on the machines I use). Fortran programmers take such checking for granted. In addition, C programmers use the *p++=*q++ construct to copy an array because historically C compilers have been too stupid to optimize "p[i] = q[i]". Fortran-8x allows an even higher level representation of array operations, for example: Fortran: do i = 1,100 C: p = array_p; p(i) = q(i) q = array_ q; end do for (i=0; i<100; i++) *p++ = *q++; is replaced by one line: p(1:100) = q(1:100) ---------------------------- I/O: In Fortran, one can write an array: write(6,1) "p", p 1 format(/a,":",1000(5f6.1/)) producing: p: 4.2 14.3 27.8 13.9 25.6 41.7 32.5 83.3 54.2 71.0 92.3 7.2 42.7 89.3 43.6 . . . How "high level" is the C code to do the same thing? Fortran includes I/O within the language definition, which allows the compiler to detect errors that C compilers can't. For example, write(6,"(i4,3f6.2)") a, b, c will produce a "data/format mismatch error" if a is not an integer, otherwise it executes correctly. What will the equivalent C code: printf("%4d%6.2f%6.2f%6.2f\n", a, b, c); do if a is not an int, or when there is not a fourth variable to print? Which is the "higher level" behavior? Fortran has list-directed i/o (default formatting) and implied loops: write(6,*) "a=", a, " i=", i, " p=", (p(j), j=1,4) Isn't this "higher level" than printf? ------------------------ Strings: Fortran strings are represented by a pointer and a length; C strings are just a pointer, with a null byte representing the end of the string. Now what kind of a scuzzy, data-dependent, low-level hack is that? Strings without bounds are what caused the chfn() security hole. How many other instances do you know of where the use of str???() instead of strn???() caused problems? Why does C need bzero(), bcopy(), etc in addition to strcpy(), strcmp(), etc? In Fortran, one writes instead of color = "red" strcpy(color, "red"); Which is "higher level"? How much code would it take to write the following in C (where for example dir = "/home/dpk" and file = "junk")? open(1, dir(:lnblnk(dir))//"/"//file(:lnblnk(file))//".f") How high level is the equivalent code in C? ---------------------------- There indeed may be no objective reality to the term "high level", but IMHO there are numerous cases (besides those involving complex numbers) where Fortran is easier to write, easier to read, and easier for the computer to compile into efficient code. Dave Kemp <Kemp@dockmaster.ncsc.mil>
thor@stout.ucar.edu (Rich Neitzel) (05/02/89)
In article <19378@adm.BRL.MIL> Kemp@DOCKMASTER.NCSC.MIL writes: > >Arrays: > Although C has an array notation, it is not used very effectively. I >don't know of any C compilers that do array bounds checking (which does >not mean that none exist, but they are not on the machines I use). >Fortran programmers take such checking for granted. BTW, on all Fortran compilers I've ever used, bounds checking is a compiler option, typically NOT a default option. Certainly when I used to write realtime programs for RSX-11M no one used the bounds checking. Not something taken for granted. > In addition, C programmers use the *p++=*q++ construct to copy an array >because historically C compilers have been too stupid to optimize >"p[i] = q[i]". Sorry, but looking at the assembler output for several Fortran compilers versus C compilers on the same machine, I find that Fortran compilers are equally "too stupid to optimize" this construct. Alas, for do i = 1, 100 for (i = 0; i < 100; i++) j(i) = k(i) j[i] = k[i]; 10 continue virtually the same assembler output was generated for both languages. If you want "smart", C is better here, since it let's the programmer optimize "around" the "dumb" compiler. Besides, if one wants to do a straight copy between two arrays, then j(1:100000) = k(1:100000) vs. bcopy(k,j,sizeof(k); In this case, for large upper bounds the C form is more efficient and certainly less data-dependent. > >Fortran includes I/O within the language definition, which allows >the compiler to detect errors that C compilers can't. Granted, but there are times when I need to "violate" the rules. For example, I once needed to print out the bit patterns for 32 bit floating point numbers. In C this was simple and easy to follow: printf("%g = %x\n",float,float); In Fortran it would require double declarations and equivalences and be less clear (at least to me :-)). >Strings: > Fortran strings are represented by a pointer and a length; C strings ^^^^^^^^^^^^ >are just a pointer, with a null byte representing the end of the string. >Now what kind of a scuzzy, data-dependent, low-level hack is that? In my humble opinion it is Fortran that is data dependent here. Try finding out how big the actual string data is versus the amount of storage allocated for the maximum size. Most Fortran compilers I've used have initialized strings with blanks! Since these are often significant characters in a string, how do you finds the end of valid data? That's right, you do it yourself. Now you need a variable to keep track of the end of data index. And as for parsing, tell me what Fortran routine can do anything similar to strtok? Gosh, you mean I have to have separate strings big enough to hold the maximum exspected character size for every parsed item? Nope, I believe it's Fortran that data- dependent. > There indeed may be no objective reality to the term "high level", but Agreed, but it seems to me that the term is used to distingish languages like C and Fortran from assembler. I would have a hard time being convinced that C is not higher level is those terms. ------------------------------------------------------------------------------- Richard Neitzel National Center For Atmospheric Research thor@thor.ucar.edu Torren med sitt skjegg Thor with the beard lokkar borni under sole-vegg calls the children to the sunny wall Gjo'i med sitt shinn Gjo with the pelts jagar borni inn. chases the children in. -------------------------------------------------------------------------------
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