Richard Heathfield wrote On 04/18/07 15:43,:
Eric Sosman said:
Malcolm McLean wrote On 04/18/07 15:06,:
You "improve" readability by using many statements
where one suffices?
This is sometimes the case, yes, although it may depend on what you mean
by "suffices".
Consider, for example, the following (genuine) code:
new->pixel[y] = clc_malloc(width * sizeof *new->pixel[y]);
if(new->pixel[y] == NULL)
Now, you /could rewrite this as:
if((new->pixel[y] = clc_malloc(width * sizeof *new->pixel[y])) == NULL)
...which certainly suffices, but I am not convinced that readability is
improved by the contraction.
Yah. "Bless you, it all depends." It is useful to
decompose lengthy statements into smaller, more easily-
comprehended pieces (not just for the reader's sake, but
for the writer's as well!), but decomposition for its own
sake is, well, compost.
McClean's example showed a perfectly simple, obvious
and easily-comprehended test, which he chose to decompose
into two statements. In the process he introduced a brand-
new variable (the point of his example was to try to expose
a difficulty concerning that unnecessary variable), plus two
additional operators. That sort of rearrangement is not
only obfuscatory (hiding a comparison behind a subtraction,
a la FORTRAN's three-way IF), but bug-inducing.
As for the malloc example, I myself usually write an
assignment statement and a separate test. This is not so
much out of a concern that the whole thing would be too
long, but to direct the focus: "I will now allocate some
memory. (By the way, I'll also check for failure.)" But
sometimes I'll gang the whole thing together, particularly
during an initialization where I'm just going to exit the
program on a failure:
if ( (buff1 = malloc(N1 * sizeof *buff1) == NULL
|| (buff2 = malloc(N2 * sizeof *buff2) == NULL
|| (buff3 = malloc(N3 * sizeof *buff3) == NULL ) {
perror ("malloc");
fputs ("No memory; bye-bye!\n", stderr);
exit (EXIT_FAILURE);
}
I think this is easier to read than three assignments, three
tests, and three error-exits, or than shuffling the test-and-
exit off to a wrapper function -- although I do *that* too,
sometimes. (Note that three assignments followed by one
three-way test and one error-exit is not quite the same: if
malloc() sets errno, the successful allocation of buff3 could
obscure why buff2's allocation failed. malloc() need not set
errno and some do not, but I take the optimistic view and try
to give the poor user all the available diagnoses, even if
they're suspect.)
I think that's a touch unfair. I'm actually on your side in this
discussion, but I think you overstate the case here.
Tastes vary. Or, "There's no point arguing with Gus."