Stylistic note on loops

E

Eric Sosman

By this you agree with a sentence with an expletive, but
whatever: This reminds my of one of my own style rules, that
I can apply to both topics discussed here: loops and the
main function:

»When two wordings are equivalent, use the shorter one.«

ITYM "When two wordings are equivalent, use the shorter."

;-)
 
L

Lew

Eric said:
ITYM "When two wordings are equivalent, use the shorter."

;-)

Simplify! Simplify! Simplify!
- Henry David Thoreau

One simplify would have sufficed.
- Ralph Waldo Emerson

However, what may be a good rule for code (and I am not saying it is) does not
make a good rule for literature. Verbosity is a tool of the literate every
bit as much as brevity.

One "simplify" may well have sufficed, or perhaps Thoreau intended the
self-contradiction, or perhaps was setting up Emerson for the reply. (They
were good friends and in the habit of trading quips.) For the latter two
purposes, one "simplify" would not have sufficed.

It's all accordin'. One may write

for ( int len; (len = read( buf )) > 0; output( buf, len ) )
{
}

with intentional bracely verbosity specifically to call attention to the empty
loopness of the construct, granting the equivalence in readability but
asserting the need for emphasis, in which case one semicolon would not suffice.
 
N

Nick

Thomas Pornin said:
In C, the lack of a return statement in a non-void-returning method is
allowed. What triggers "undefined behaviour" (aka "all of Hell is
breaking loose") is reaching the closing '}' of a function _and_ trying
to use the returned value (or, more appropriately, the value which
should have been returned but was not). In a C implementation with a
well-defined compilation phase (that's the normal state of affairs in
C), the compilation MUST NOT fail on such a lack of a return statement
in a non-void-returning function: problems implied by that lack of
return may become apparent only at runtime.

I've often wondered - although I'd never write it - about something like
this:

int process_items(struct thing *items, int mode) {
if(mode == 0) {
/* do some stuff */
return;
} else {
int count = 0;
/* do some other stuff, counting items */
return count;
}
}

int main(void) {
struct thing *stuff = create_items();
/* set up items etc ... */
process_items(stuff,1);
printf("There are %d\n",process_items(stuff));
return EXIT_SUCCESS;
}

As I said, lots of reasons not to do it that way - including that this
toy is clearly a case for a single return and a function-wide count variable that
is always returned - but is it entirely OK?
 
C

ClassCastException

Simplify! Simplify! Simplify!
- Henry David Thoreau

One simplify would have sufficed.
- Ralph Waldo Emerson

However, what may be a good rule for code (and I am not saying it is)
does not make a good rule for literature. Verbosity is a tool of the
literate every bit as much as brevity.

One "simplify" may well have sufficed, or perhaps Thoreau intended the
self-contradiction, or perhaps was setting up Emerson for the reply.
(They were good friends and in the habit of trading quips.) For the
latter two purposes, one "simplify" would not have sufficed.

It's all accordin'. One may write

for ( int len; (len = read( buf )) > 0; output( buf, len ) ) {
}

with intentional bracely verbosity specifically to call attention to the
empty loopness of the construct, granting the equivalence in readability
but asserting the need for emphasis, in which case one semicolon would
not suffice.

Emphasis also provides a fourth reason for tripling the "Simplify!".
 
B

Ben Bacarisse

Nick said:
Thomas Pornin <[email protected]> writes:
I've often wondered - although I'd never write it - about something like
this:

int process_items(struct thing *items, int mode) {
if(mode == 0) {
/* do some stuff */
return;
} else {
int count = 0;
/* do some other stuff, counting items */
return count;
}
}

int main(void) {
struct thing *stuff = create_items();
/* set up items etc ... */
process_items(stuff,1);
printf("There are %d\n",process_items(stuff));

There should be a second argument in this call, but that's not the point
of your post.
return EXIT_SUCCESS;
}

As I said, lots of reasons not to do it that way - including that this
toy is clearly a case for a single return and a function-wide count
variable that is always returned - but is it entirely OK?

No, not in C99. The presence of either a return with an expression in a
void function; or the presence of one without in a non-void function are
constraint violations in C99.

If you remove the first return statement altogether (and thus simply
allow execution to "fall off the end" of the function) then the program
is OK (presuming that there are all the right declarations, of course).
 
T

Tom Anderson

In C, the lack of a return statement in a non-void-returning method is
allowed. What triggers "undefined behaviour" (aka "all of Hell is
breaking loose") is reaching the closing '}' of a function _and_ trying
to use the returned value (or, more appropriately, the value which
should have been returned but was not). In a C implementation with a
well-defined compilation phase (that's the normal state of affairs in
C), the compilation MUST NOT fail on such a lack of a return statement
in a non-void-returning function: problems implied by that lack of
return may become apparent only at runtime.

Thanks - and to Eric - for the explanation.
Of course, nothing of the above prevents a C compiler from emitting a
warning about the lack of return.

Nor, presumably, from doing something crafty to cause that usage to blow
up loudly at runtime.

tom
 
T

Tom Anderson

By this you agree with a sentence with an expletive, but
whatever: This reminds my of one of my own style rules, that
I can apply to both topics discussed here: loops and the
main function:

?When two wordings are equivalent, use the shorter one.?

I can assure you that that sentence is not equivalent to the one without
the expletive. I have CVS records of a week of code cleanup to prove it.

tom
 
B

Ben Bacarisse

Tom Anderson said:
Thanks - and to Eric - for the explanation.


Nor, presumably, from doing something crafty to cause that usage to
blow up loudly at runtime.

That depends on what you mean by "that usage"!

Just to be 100% clear: the simple fact of omitting the return (in some
path through the function) can not, of itself, cause anything to blow up
at run-time. Anything at all is permitted, however, if the caller
attempts to use the value that was not returned (if you see what I
mean).

This is probably what you meant, but given the placement of the remark
there was some scope for other readers to misunderstand.
 
R

Robert Klemme

I think Python is the last language I'd use for pseudocode. No-one
writing Python can resist using all it's features which renders it
incomprehensible to anyone else. And for porting code, it is also
necessary to duplicate it's myriad libraries.

Probably Lua is better for that role, being far simpler with less
built-in stuff.

Of course I have to throw in Ruby here. Very clean syntax, clean OO
implementation and no significant whitespace. I often find that Ruby
code looks like pseudo code - but it actually can be executed. :)

Kind regards

robert
 
N

Nick

Ben Bacarisse said:
There should be a second argument in this call, but that's not the point
of your post.

Well spotted.
No, not in C99. The presence of either a return with an expression in a
void function; or the presence of one without in a non-void function are
constraint violations in C99.

If you remove the first return statement altogether (and thus simply
allow execution to "fall off the end" of the function) then the program
is OK (presuming that there are all the right declarations, of course).

Thanks for confirming it. It's odd that an int function that ends with
"return;}" is a constraint violation but one that ends with a plain "}"
isn't, since for a void function they'd both be OK.
 
K

Keith Thompson

Nick said:
Thanks for confirming it. It's odd that an int function that ends with
"return;}" is a constraint violation but one that ends with a plain "}"
isn't, since for a void function they'd both be OK.

Yes, it's odd, but it's easier for a compiler to determine that a
return with no expression in a non-void function, or a return with
an expression in a void function, is an error, than to detect a
*missing* return statement.

For example:

int spin(void) {
while (1) {
continue;
}
}

The missing return isn't really an error, since the closing brace can
never be reached.

Also;

int foo(void) {
if (condition) {
return 42;
}
}

This isn't an error if "condition" is always true.

Reaching the closing "}" of a non-void function is really a run-time
error that can sometimes, but not always, be detected at compile
time.

The standard *could* have required that no execution path in a
non-void function may reach the closing "}", but that would require
more analysis than the standard generally requires compilers to
perform. Compilers are of course free to warn about missing returns.

Something I never noticed before: as far as I can tell, this:

int func(void) {
struct { double x; } result = { 0.0 };
return result;
}

does not violate any constraints. Its behavior is undefined, but
only by an omission of the definition of the behavior. C99 6.8.6.4p3
says:

If the expression has a type different from the return type of
the function in which it appears, the value is converted as if by
assignment to an object having the return type of the function.

An assignment won't convert from a struct type to int, so there's no
definition of the behavior. Was this an oversight?

Followups redirected to comp.lang.c; this is probably beyond what's
topical for comp.lang.java.programmer.
 
T

Tom Anderson

That depends on what you mean by "that usage"!

Just to be 100% clear: the simple fact of omitting the return (in some
path through the function) can not, of itself, cause anything to blow up
at run-time. Anything at all is permitted, however, if the caller
attempts to use the value that was not returned (if you see what I
mean).

Yes - sorry, that's what i was thinking of, and i didn't explain it
clearly. You could do something in the calling convention so that the
caller had to check a real value had been pushed onto the stack, perhaps.
Or specialise the function into a version called in void contexts, and a
version called in contexts where the return value is used, with the latter
doing the checking. Or something cleverer.

tom
 
T

Tom Anderson

Of course I have to throw in Ruby here. Very clean syntax, clean OO
implementation and no significant whitespace. I often find that Ruby code
looks like pseudo code

Except that significant whitespace is usually a notable feature of
pseudocode!

And of course the sigils. I believe this is ruby:

@count = 99

What purpose does the @ serve?

tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,780
Messages
2,569,609
Members
45,253
Latest member
BlytheFant

Latest Threads

Top