Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: goto

4 views
Skip to first unread message
Message has been deleted

Jamie

unread,
Jun 23, 2009, 1:21:56 PM6/23/09
to
In <slrnh419uv....@bowser.marioworld>,
Ben C <spam...@spam.eggs> mentions:
>Best way in C programming to do early-returns-with-cleanup in my
>opinion. Yes avoid it for general control flow (the usual loops, if, and
>switch are much better).

I like that style, I suppose it's like using tables when they're
useful.

Of course, in dynamic languages and where cleanup/free isn't really
an issue, early returns are good.

"Early returns" (w/out a closing </table> tag)... not so good :-)

Jamie
--
http://www.geniegate.com Custom web programming
Perl * Java * UNIX User Management Solutions

Richard Heathfield

unread,
Jun 23, 2009, 3:09:49 PM6/23/09
to
Tim Streater said:

<snip>

> I'm certainly not going to avoid the return statement when
> inevitably the alternative is if's nested 20 deep or whatever.
> That just gives you an impenetrable and unmaintainable mess.

Without in any way wishing to dissuade you from your choice, I would
just like to add that it is not only possible but reasonably simple
to adopt a single-return strategy without making the code
unreadable or unmaintainable. The key is strict modularisation.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Forged article? See
http://www.cpax.org.uk/prg/usenet/comp.lang.c/msgauth.php
"Usenet is a strange place" - dmr 29 July 1999

Richard

unread,
Jun 23, 2009, 4:08:01 PM6/23/09
to
Richard Heathfield <r...@see.sig.invalid> writes:

> Tim Streater said:
>
> <snip>
>
>> I'm certainly not going to avoid the return statement when
>> inevitably the alternative is if's nested 20 deep or whatever.
>> That just gives you an impenetrable and unmaintainable mess.
>
> Without in any way wishing to dissuade you from your choice, I would
> just like to add that it is not only possible but reasonably simple
> to adopt a single-return strategy without making the code
> unreadable or unmaintainable. The key is strict modularisation.

Single returns are unnecessary and are purely an anal "style" thing IMO.

If someone thinks something like

,----
| if(errorCheck(pArgs))
| return MY_FAIL;
|
| /* ok lets go */
`----

is confusing or bad style they need their head examining.

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

Paul N

unread,
Jun 23, 2009, 5:40:49 PM6/23/09
to
On 23 June, 20:09, Richard Heathfield <r...@see.sig.invalid> wrote:
> Without in any way wishing to dissuade you from your choice, I would
> just like to add that it is not only possible but reasonably simple
> to adopt a single-return strategy without making the code
> unreadable or unmaintainable. The key is strict modularisation.

To what extent is "strict modularisation" the same as "putting the
inner loops into separate functions"?

(By the way, Google seems to have started crediting my posts to "Paul
N" rather than my email address of gw7rib etc. In case anyone's
confused.)

Tony

unread,
Jun 23, 2009, 10:58:18 PM6/23/09
to
Paul N wrote:
> On 23 June, 20:09, Richard Heathfield <r...@see.sig.invalid> wrote:
>> Without in any way wishing to dissuade you from your choice, I would
>> just like to add that it is not only possible but reasonably simple
>> to adopt a single-return strategy without making the code
>> unreadable or unmaintainable. The key is strict modularisation.

I've never found the "single return strategy" to be valid because too many
other cases apply where the semantics of a return are compelling. For
instance, the function pattern:

void SomeFunc(uint32 good)
{
if(!good)
return;

// process of elimination above makes code here
// more comprehensible and maintainable.

return;
}

Then there's the example of using returns in switch case statements rather
than breaks. Then there's the example of returning from a while or for loop
instead of breaking out to the nth/hard-to-know level.

Surely there are more examples of why a single return strategy is nothing
more than anal retentiveness.

(Next up: Why 'goto' is not inherently bad!)


Ben C

unread,
Jun 24, 2009, 3:12:23 AM6/24/09
to
On 2009-06-23, Jamie <nos...@geniegate.com> wrote:
> In <slrnh419uv....@bowser.marioworld>,
> Ben C <spam...@spam.eggs> mentions:
>>Best way in C programming to do early-returns-with-cleanup in my
>>opinion. Yes avoid it for general control flow (the usual loops, if, and
>>switch are much better).
>
> I like that style, I suppose it's like using tables when they're
> useful.
>
> Of course, in dynamic languages and where cleanup/free isn't really
> an issue, early returns are good.

Certainly, and often in C too, for functions that don't need to
allocate/free etc.

One of the keys to successful C programming IMO is separating as best
you can all the housekeeping clutter from the real code.

> "Early returns" (w/out a closing </table> tag)... not so good :-)

Yes, good analogy :)

Boon

unread,
Jun 24, 2009, 5:00:59 AM6/24/09
to
Richard wrote:

> Single returns are unnecessary and are purely an anal "style" thing IMO.
>
> If someone thinks something like
>
> ,----
> | if(errorCheck(pArgs))
> | return MY_FAIL;
> |
> | /* ok lets go */
> `----
>

> is confusing or bad style they need their head examined.

What if, at this point, you've locked 3 mutexes, opened 5 files,
allocated 7 memory blocks, and done other stuff that needs to be
undone in a specific order?

BartC

unread,
Jun 24, 2009, 5:08:44 AM6/24/09
to

"Boon" <root@localhost> wrote in message
news:4a41eb41$0$294$7a62...@news.club-internet.fr...

What if you've only locked one mutex (whatever that is), opened two files
(one of them not one of the 5), and allocated only 3 of the 7 memory blocks,
plus a couple extra not known to the rest of the code?

It will be a job unscrambling that lot with a single return, without doing
things a completely different way. And that means doing things differently
(and more complicatedly) just for the sake of having a single return.

And what if no mutexes, files or blocks are active?

--
Bart

BartC

unread,
Jun 24, 2009, 5:13:49 AM6/24/09
to

"Tony" <to...@my.net> wrote in message
news:Gvg0m.3589$Rb6....@flpi147.ffdc.sbc.com...

> Paul N wrote:
>> On 23 June, 20:09, Richard Heathfield <r...@see.sig.invalid> wrote:
>>> Without in any way wishing to dissuade you from your choice, I would
>>> just like to add that it is not only possible but reasonably simple
>>> to adopt a single-return strategy without making the code
>>> unreadable or unmaintainable. The key is strict modularisation.
>
> I've never found the "single return strategy" to be valid because too many
> other cases apply where the semantics of a return are compelling.
...

> Surely there are more examples of why a single return strategy is nothing
> more than anal retentiveness.

I think it's also faster (what's the point of jumping to L to return when
you can return just as well here).

> (Next up: Why 'goto' is not inherently bad!)

(Goto bad? Who says?)

--
Bart

Willem

unread,
Jun 24, 2009, 5:18:35 AM6/24/09
to
Boon wrote:
) Richard wrote:
)> Single returns are unnecessary and are purely an anal "style" thing IMO.
)>
)> If someone thinks something like
)>
)> ,----
)> | if(errorCheck(pArgs))
)> | return MY_FAIL;
)> |
)> | /* ok lets go */
)> `----
)>
)> is confusing or bad style they need their head examined.
)
) What if, at this point, you've locked 3 mutexes, opened 5 files,
) allocated 7 memory blocks, and done other stuff that needs to be
) undone in a specific order?

Then your function is way too complex and should be
divided up into subfunctions immediately.


Besides, why impose a "style" requirement of one-exit-point to all
functions for the 1% that happens to be so complex as to have 3 mutexes,
5 files and 7 memory blocks, which need to be deallocated in a specific
order ? Why make the other 99% of functions suffer ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Richard

unread,
Jun 24, 2009, 7:02:21 AM6/24/09
to
Boon <root@localhost> writes:

If you have then you're a pretty shitty programmer if the unlocking is
in this function and you put that return there ...

But if it IS then, err, dont do this style of return there and then ....

Hang on. What do you mean?

CLEARLY you wont use a return as above if you have something like
that. What a silly thing to say.

Richard

unread,
Jun 24, 2009, 7:03:01 AM6/24/09
to
"BartC" <ba...@freeuk.com> writes:

What are these things? Are they in the C standard? .....

Ben C

unread,
Jun 24, 2009, 7:04:25 AM6/24/09
to

Use goto.

Boon

unread,
Jun 24, 2009, 7:23:34 AM6/24/09
to
Richard wrote:

> "BartC" <ba...@freeuk.com> writes:


>
>> Boon wrote:
>>
>>> Richard wrote:
>>>
>>>> Single returns are unnecessary and are purely an anal "style" thing IMO.
>>>>
>>>> If someone thinks something like
>>>>
>>>> ,----
>>>> | if(errorCheck(pArgs))
>>>> | return MY_FAIL;
>>>> | | /* ok lets go */
>>>> `----
>>>>
>>>> is confusing or bad style they need their head examined.
>>> What if, at this point, you've locked 3 mutexes, opened 5 files,
>>> allocated 7 memory blocks, and done other stuff that needs to be
>>> undone in a specific order?
>> What if you've only locked one mutex (whatever that is), opened two files
>> (one of them not one of the 5), and allocated only 3 of the 7 memory blocks,
>> plus a couple extra not known to the rest of the code?
>>
>> It will be a job unscrambling that lot with a single return, without doing
>> things a completely different way. And that means doing things differently
>> (and more complicatedly) just for the sake of having a single return.
>>
>> And what if no mutexes, files or blocks are active?
>
> What are these things? Are they in the C standard? ...

You don't know about files and memory blocks? Do you write functions that leak
memory and "file descriptors" when they exit prematurely?

Are you /trying/ to sound like a regular? :-)

Ignore the mutexes, and focus on the concept (stuff that needs to be undone in a
specific order).

Regards.

Chris Dollin

unread,
Jun 24, 2009, 7:33:17 AM6/24/09
to
Tony wrote:

> Paul N wrote:
>> On 23 June, 20:09, Richard Heathfield <r...@see.sig.invalid> wrote:
>>> Without in any way wishing to dissuade you from your choice, I would
>>> just like to add that it is not only possible but reasonably simple
>>> to adopt a single-return strategy without making the code
>>> unreadable or unmaintainable. The key is strict modularisation.
>
> I've never found the "single return strategy" to be valid because too many
> other cases apply where the semantics of a return are compelling. For
> instance, the function pattern:
>
> void SomeFunc(uint32 good)
> {
> if(!good)
> return;
>
> // process of elimination above makes code here
> // more comprehensible and maintainable.
>
> return;
> }

Since this is trivially convertible to the more understandable

if (good)
{ stuff }

it's not a very good example.

(If you're argument is that `stuff` might be long and complicated
enough that you can't see than nothing happens if !good, my response
is Birmingham!, ie, I wouldn't start from there -- if `stuff` is that
complicated, FIX IT NOW.)

> Then there's the example of using returns in switch case statements rather
> than breaks. Then there's the example of returning from a while or for loop
> instead of breaking out to the nth/hard-to-know level.

Those are better examples.

--
"It is seldom good news." ~Crystal Ball~, /The Tough Guide to Fantasyland/

Hewlett-Packard Limited Cain Road, Bracknell, registered no:
registered office: Berks RG12 1HN 690597 England

Richard

unread,
Jun 24, 2009, 7:38:28 AM6/24/09
to
Boon <root@localhost> writes:

Erm, I was joking ....

>
> Are you /trying/ to sound like a regular? :-)
>
> Ignore the mutexes, and focus on the concept (stuff that needs to be undone in a
> specific order).

Why? Then you do it outside of that function or you dont use that return
style.

Its no magic.

Dont use it if it WILL screw up the system. Its hardly rocket science.

>
> Regards.

Ben Bacarisse

unread,
Jun 24, 2009, 8:12:18 AM6/24/09
to
Ben C <spam...@spam.eggs> writes:

That would be at the bottom of my list of options. The "meta"
solution is a language where early return can do the cleanup, but if
we have to use C I would want to try (a) simplifying the
function/design to avoid this resource-heavy function; (b) find a
structured alternative.

The trouble with the goto version is that it links the top and the
bottom of the function. To be sure the exit code does the right
thing, you need to check the initialisations and assignments at the
top. Any changes at either end need cause the other end to be
checked. It's not a hopeless design[1], but even with a complex set
of resources you can sometimes get away with one "if" and keep the
cleanup close to the allocation, which I find easier to read.

[1] and with 2 gotos you can put the cleanup at the top!

--
Ben.

Ben C

unread,
Jun 24, 2009, 2:32:11 PM6/24/09
to
On 2009-06-24, Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
> Ben C <spam...@spam.eggs> writes:
>
>> On 2009-06-24, Boon <root@localhost> wrote:
>>> Richard wrote:
>>>
>>>> Single returns are unnecessary and are purely an anal "style" thing IMO.
>>>>
>>>> If someone thinks something like
>>>>
>>>> ,----
>>>> | if(errorCheck(pArgs))
>>>> | return MY_FAIL;
>>>> |
>>>> | /* ok lets go */
>>>> `----
>>>>
>>>> is confusing or bad style they need their head examined.
>>>
>>> What if, at this point, you've locked 3 mutexes, opened 5 files,
>>> allocated 7 memory blocks, and done other stuff that needs to be
>>> undone in a specific order?
>>
>> Use goto.
>
> That would be at the bottom of my list of options. The "meta"
> solution is a language where early return can do the cleanup, but if
> we have to use C I would want to try (a) simplifying the
> function/design to avoid this resource-heavy function;

If a function is really too big and doing too many things then it's
better to split it up. But often it's not-- it's a "constructor" (or
rather initializer) type of function, and so _does_ allocate and
initialize a lot of things. You really want that all in one place. YMMV.

> (b) find a
> structured alternative.
>
> The trouble with the goto version is that it links the top and the
> bottom of the function. To be sure the exit code does the right
> thing, you need to check the initialisations and assignments at the
> top.

Set _everything_ to NULL (or some equivalent sentinel) first, before
trying to allocate or initialize _anything_. Then at the bottom,
whatever isn't NULL (etc.) needs to be freed/deleted/etc. Of course with
free you can just free NULL anyway (and I generally write other "delete"
functions like that too-- NULL-tolerating, and partially-initialized
tolerating).

Paul Hsieh

unread,
Jun 24, 2009, 2:42:38 PM6/24/09
to

Your destructors get invoked in exact reverse order in which they were
invoked, so you wrap them up in objects ... oh yeah, I forgot C
doesn't have that concept does it? Oh well. In that case you
suffer. You have to write your clean up code exactly and precisely
for every return block. Having a common exit path does not actually
save you because you become restricted in the control flow of your
main program. You can actually write nested return blocks that link
to each other through goto -- with well chosen label names, insert and
deletion of code actually becomes syntax checked. But then people
really could accuse you of writing spaghetti code.

In any event, a more serious suggestion is that you can use wrapping
function calls for each opened stack-lifetime object groupings. So
that your leaf functions can do "middle returns" with impunity, and
your wrapper just needs to check the return value to decide if its
needs to clean up and pass the error upwards, or whatever semantic it
wants to follow on success.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Ben Bacarisse

unread,
Jun 24, 2009, 7:39:35 PM6/24/09
to
Ben C <spam...@spam.eggs> writes:

Well I said "try". I agree it may not be possible.

>> (b) find a
>> structured alternative.
>>
>> The trouble with the goto version is that it links the top and the
>> bottom of the function. To be sure the exit code does the right
>> thing, you need to check the initialisations and assignments at the
>> top.
>
> Set _everything_ to NULL (or some equivalent sentinel) first, before
> trying to allocate or initialize _anything_. Then at the bottom,
> whatever isn't NULL (etc.) needs to be freed/deleted/etc. Of course with
> free you can just free NULL anyway (and I generally write other "delete"
> functions like that too-- NULL-tolerating, and partially-initialized
> tolerating).

I know how to do it! My point was that someone reading the code has
to look at two split locations: the initialisation at the top and the
clean-up code to the bottom. It is sometimes possible to keep them
close together or at least closer together than the usual "jump to
cleanup" pattern does. I am sure there are pathological cases where
the goto wins, but I have not yet seen an example that I have not been
tempted to re-write. I am sure it comes down to how I was taught.

On a minor note, I think you are too strict to require that everything
be set before your try to allocate anything (and it may be you did not
mean it quite like that). I am quite happy when I see:

char *b1 = malloc(...);
char *b2 = malloc(...);
int *data = malloc(....);
if (!b1 || !b2 || !data) {
free(b1); free(b2); free(data);
return FAILED;
}

because the state of everything is still predictable.

--
Ben.

Ben C

unread,
Jun 25, 2009, 3:25:28 AM6/25/09
to
On 2009-06-24, Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
> Ben C <spam...@spam.eggs> writes:
[...]

>> Set _everything_ to NULL (or some equivalent sentinel) first, before
>> trying to allocate or initialize _anything_. Then at the bottom,
>> whatever isn't NULL (etc.) needs to be freed/deleted/etc. Of course with
>> free you can just free NULL anyway (and I generally write other "delete"
>> functions like that too-- NULL-tolerating, and partially-initialized
>> tolerating).
>
> I know how to do it! My point was that someone reading the code has
> to look at two split locations: the initialisation at the top and the
> clean-up code to the bottom. It is sometimes possible to keep them
> close together or at least closer together than the usual "jump to
> cleanup" pattern does. I am sure there are pathological cases where
> the goto wins, but I have not yet seen an example that I have not been
> tempted to re-write. I am sure it comes down to how I was taught.
>
> On a minor note, I think you are too strict to require that everything
> be set before your try to allocate anything (and it may be you did not
> mean it quite like that). I am quite happy when I see:
>
> char *b1 = malloc(...);
> char *b2 = malloc(...);
> int *data = malloc(....);
> if (!b1 || !b2 || !data) {
> free(b1); free(b2); free(data);
> return FAILED;
> }
>
> because the state of everything is still predictable.

I don't mind when I see that (I'm generally tolerant of other people's
styles-- the desire to bring order to the cosmos is not a healthy one).

But for me it helps to stick to the routine because then there's less
chance of getting it wrong.

But for very small functions, I don't bother with that goto end
business. It's only when there's any risk that things might get a bit
confusing.

Also I've done quite a bit of work on projects where people use memory
"handles" (you know the extra redirection so they can reshuffle their
heap-- misguided IMO but whadayagonnado). This means there's practically
always a whole lot of things to "unlock" even in functions that wouldn't
otherwise do anything that needed any cleanup.

Nick Keighley

unread,
Jun 25, 2009, 3:29:51 AM6/25/09
to

since its checking its arguments it probably occurred at the
beginning of the function before it did all that stuff.

If you have a single function that locks 3 mutexs, opens 5 files
and allocates 7 memory blocks then I'd argue your function is too
complicated

Nick Keighley

unread,
Jun 25, 2009, 3:36:20 AM6/25/09
to
On 23 June, 18:21, nos...@geniegate.com (Jamie) wrote:
> In <slrnh419uv.35v.spams...@bowser.marioworld>,
> Ben C <spams...@spam.eggs> mentions:

> >Best way in C programming to do early-returns-with-cleanup in my
> >opinion. Yes avoid it for general control flow (the usual loops, if, and
> >switch are much better).
>
> I like that style, I suppose it's like using tables when they're
> useful.
>
> Of course, in dynamic languages and where cleanup/free isn't really
> an issue, early returns are good.

why is cleanup/free not an issue with dynamic languages?

<snip>

Tony

unread,
Jun 26, 2009, 5:34:10 AM6/26/09
to

"Chris Dollin" <chris....@hp.com> wrote in message
news:h1t2va$gfv$1...@news-pa1.hpl.hp.com...

> Tony wrote:
>
>> Paul N wrote:
>>> On 23 June, 20:09, Richard Heathfield <r...@see.sig.invalid> wrote:
>>>> Without in any way wishing to dissuade you from your choice, I would
>>>> just like to add that it is not only possible but reasonably simple
>>>> to adopt a single-return strategy without making the code
>>>> unreadable or unmaintainable. The key is strict modularisation.
>>
>> I've never found the "single return strategy" to be valid because too
>> many
>> other cases apply where the semantics of a return are compelling. For
>> instance, the function pattern:
>>
>> void SomeFunc(uint32 good)
>> {
>> if(!good)
>> return;
>>
>> // process of elimination above makes code here
>> // more comprehensible and maintainable.
>>
>> return;
>> }
>
> Since this is trivially convertible to the more understandable
>
> if (good)
> { stuff }
>
> it's not a very good example.

I'd rather do the process of elimination than have the mainline code
indented and in braces even though your way is insignificantly more
efficient. I think of it as akin to precondition checking (of course one
cannot really do precondition checking from within a called function, but
that's what they call it). Just personal preference.

Tony

unread,
Jun 26, 2009, 5:41:39 AM6/26/09
to

"Boon" <root@localhost> wrote in message
news:4a41eb41$0$294$7a62...@news.club-internet.fr...

No need to worry about that if you move to C++. Those tiny classes one
writes to automagically handle that kind of thing changes the way you think
about programming. What's "bad" style in C, may be because of a weakness in
the language. Add a few error handling patterns and you may find C++
compelling (I do). Adding just a few things to C could make it "a bettter
C++" (not that I'm saying anything original with this statement)!


Spiro Trikaliotis

unread,
Jun 28, 2009, 8:51:29 AM6/28/09
to
Hello,

Boon wrote:

Then use

do {
if (errorCheck(pAtgs))
break;

/* ok lets go */

} while (0);

/* cleanup the mutexes, files, whatever */


Yes, I know, this is not always possible, but I am getting more and more
used to that pattern. IMHO, it is much more structured than arbitrary
gotos. The main problem is in nested loops, though.

Regards,
Spiro.

--
Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/

Lie Ryan

unread,
Jun 28, 2009, 9:58:01 AM6/28/09
to

In dynamic language, most cleanups are automatic.

Kenny McCormack

unread,
Jun 28, 2009, 11:50:22 AM6/28/09
to
In article <JFK1m.1477$ze1...@news-server.bigpond.net.au>,

What, exactly, do you mean by "dynamic language" ?

BartC

unread,
Jun 28, 2009, 12:02:41 PM6/28/09
to

"Kenny McCormack" <gaz...@shell.xmission.com> wrote in message
news:h283fu$n72$2...@news.xmission.com...

I'd also like to know what dynamic language would free resources such as
files, windows, and network connections on return from a function.
Especially if the purpose of the function was to create such a resource.

--
Bart

Kenny McCormack

unread,
Jun 28, 2009, 2:04:23 PM6/28/09
to
In article <BuM1m.48890$OO7....@text.news.virginmedia.com>,
BartC <ba...@freeuk.com> wrote:
...

>>>In dynamic language, most cleanups are automatic.
>>
>> What, exactly, do you mean by "dynamic language" ?
>
>I'd also like to know what dynamic language would free resources such as
>files, windows, and network connections on return from a function.
>Especially if the purpose of the function was to create such a resource.

Very true, of course.

But, just for the record, my post was mainly about definitions/semantics.
I suspect that when Mr. Ryan uses the term "dynamic language", he really
just means "script language", but somehow, the D word is more, well,
"dynamic".

Nobody

unread,
Jun 28, 2009, 4:38:52 PM6/28/09
to
On Sun, 28 Jun 2009 18:04:23 +0000, Kenny McCormack wrote:

>>>>In dynamic language, most cleanups are automatic.
>>>
>>> What, exactly, do you mean by "dynamic language" ?
>>
>>I'd also like to know what dynamic language would free resources such as
>>files, windows, and network connections on return from a function.
>>Especially if the purpose of the function was to create such a resource.
>
> Very true, of course.
>
> But, just for the record, my post was mainly about definitions/semantics.
> I suspect that when Mr. Ryan uses the term "dynamic language", he really
> just means "script language", but somehow, the D word is more, well,
> "dynamic".

FWIW, I assumed he was referring to languages which use automatic garbage
collection, so objects are destroyed once there are no longer any
references to them.

If a function creates an object with the intent of returning or storing a
reference to it, but returns without doing so, the object will have no
references and will be destroyed automatically.

Stephen Sprunk

unread,
Jun 28, 2009, 4:53:23 PM6/28/09
to
BartC wrote:
> I'd also like to know what dynamic language would free resources such as
> files, windows, and network connections on return from a function.
> Especially if the purpose of the function was to create such a resource.

If the file, window, or network connection was encapsulated in an
object, then the destructor for that object would naturally do the
freeing. If the function returns the object (or a reference to it,
depending on the language), the object would obviously not be
garbage-collected at that point.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Isaac Jaffe

BartC

unread,
Jun 28, 2009, 5:57:58 PM6/28/09
to

"Stephen Sprunk" <ste...@sprunk.org> wrote in message
news:8LQ1m.2709$OF1....@nlpi069.nbdc.sbc.com...

> BartC wrote:
>> I'd also like to know what dynamic language would free resources such as
>> files, windows, and network connections on return from a function.
>> Especially if the purpose of the function was to create such a resource.
>
> If the file, window, or network connection was encapsulated in an
> object, then the destructor for that object would naturally do the
> freeing. If the function returns the object (or a reference to it,
> depending on the language), the object would obviously not be
> garbage-collected at that point.

Yes, *if*. And I'd still foresee a lot of problems relying on language
features, designed to garbage collect variables, to take care of large,
tangible resources which have existence outside the function, module or even
application.

And how do you 'free' a file exactly... the cleanup needed may not be as
black and white as freeing or not freeing.

My point is a dynamic language (which need not use oop) could have the same
sorts of problems, although it would probably have to worry less about
freeing array and string space and such languagey things.

--
Bart

Kaz Kylheku

unread,
Jun 28, 2009, 8:00:28 PM6/28/09
to

In many dynamic languages, only memory cleanup is automatic. Other kinds of
cleanup can be tied to memory cleanup via finalization mechanisms, but then the
cleanup is still not timely.

For instance, when a stream object which holds an open file is computed as
unreachable by the garbage collector, the file can be closed, in addition to
that stream object's memory being recycled. But this may happen late. What if
some other process is waiting for that one to release the file?

Cleanup can be tied to invocations of lexical scopes (``unwind protect'') in
some of these languages, but that is not a core ``dynamic'' feature. The
feature is found in static languages also (e.g. Java ``finally'', C++
destructors).

luserXtrog

unread,
Jun 28, 2009, 10:16:26 PM6/28/09
to
On Jun 28, 7:51 am, Spiro Trikaliotis
<usenet-200...@spiro.trikaliotis.net> wrote:

<snippificated>

> > What if, at this point, you've locked 3 mutexes, opened 5 files,
> > allocated 7 memory blocks, and done other stuff that needs to be
> > undone in a specific order?
>
> Then use
>
>   do {
>      if (errorCheck(pAtgs))
>         break;
>
>      /* ok lets go */
>   } while (0);
>
>   /* cleanup the mutexes, files, whatever */
>
> Yes, I know, this is not always possible, but I am getting more and more
> used to that pattern. IMHO, it is much more structured than arbitrary
> gotos. The main problem is in nested loops, though.

Caution: the meaning of 'do' followed by 'if' may not be obvious
to some programmers.

--
lxt
i didn't really mean it.

Richard Bos

unread,
Jul 5, 2009, 7:31:53 AM7/5/09
to
Willem <wil...@snail.stack.nl> wrote:

> Boon wrote:
> ) Richard wrote:
> )> Single returns are unnecessary and are purely an anal "style" thing IMO.
> )>
> )> If someone thinks something like
> )>
> )> ,----
> )> | if(errorCheck(pArgs))
> )> | return MY_FAIL;
> )> |
> )> | /* ok lets go */
> )> `----
> )>
> )> is confusing or bad style they need their head examined.
> )
> ) What if, at this point, you've locked 3 mutexes, opened 5 files,
> ) allocated 7 memory blocks, and done other stuff that needs to be
> ) undone in a specific order?
>
> Then your function is way too complex and should be
> divided up into subfunctions immediately.

No, then you're too late. I recently wrote a function which opened four
files and allocated a lot of memory blocks (but locked no mutexes). I
had no problem using the above method for checking its input, and there
was no way to divide this function up without making it more, not less,
complicated.

_First_ you check everything that you can check, such as arguments, and
abort early if anything is wrong. That done, you allocate resources, and
depending on how early in the function this is, either clean up what
little you need to and then abort early, or jump to your end-of-function
cleanup point. Halfway through the function, you may need to dynamically
allocate more resources, and if at that point you run out, again, you
jump to your late bailout point. At this bailout point, you check which
resources you have opened, and release them.
This way, you have one block of early aborts, nicely maintainably kept
together; one late exit, with the necessary release functions; and
_perhaps_ one or two jumps to that late bailout. In most cases by far,
you'll be able to make those jumps consist of breaks instead of gotos.

Richard

Ben C

unread,
Jul 5, 2009, 5:01:57 PM7/5/09
to

OK, and what you describe sounds to me like a good style. But what's
actually _wrong_ with just using goto for those jumps instead of break?
I mean, who are we kidding?

Flash Gordon

unread,
Jul 6, 2009, 1:16:31 AM7/6/09
to
Ben C wrote:
> On 2009-07-05, Richard Bos <ral...@xs4all.nl> wrote:

<snip>

>> This way, you have one block of early aborts, nicely maintainably kept
>> together; one late exit, with the necessary release functions; and
>> _perhaps_ one or two jumps to that late bailout. In most cases by far,
>> you'll be able to make those jumps consist of breaks instead of gotos.
>
> OK, and what you describe sounds to me like a good style. But what's
> actually _wrong_ with just using goto for those jumps instead of break?
> I mean, who are we kidding?

If you see a label you have to check the entire function to see how it
is used...

if (early_prob) goto err;
...

err:
tidy up
if (tidy_up_failed) goto err;
more tidy up

Obviously bad style, but you have to check for it anyway if you want to
know it hasn't been done. With a break you don't have to worry about
this, although it does have its own problems.
--
Flash Gordon

Richard Bos

unread,
Jul 6, 2009, 7:09:31 AM7/6/09
to
Ben C <spam...@spam.eggs> wrote:

What's wrong is that the goto could go anywhere, while the break can
only go to the end of the loop. What's more, the goto could come from[1]
anywhere, as well. Sure, well-written code does not use goto like that,
but if you don't use it when you don't need it, you don't have to worry
about it. Possibly more importantly, neither does anyone else who reads
your code.

Richard

[1] Just be grateful C was designed by dmr, and not by Lyon and Woods.
Our code would be full of twisty little COME FROMs, all alike.

Richard

unread,
Jul 6, 2009, 9:07:52 AM7/6/09
to
ral...@xs4all.nl (Richard Bos) writes:

> Ben C <spam...@spam.eggs> wrote:
>
>> On 2009-07-05, Richard Bos <ral...@xs4all.nl> wrote:
>> > _First_ you check everything that you can check, such as arguments, and
>> > abort early if anything is wrong. That done, you allocate resources, and
>> > depending on how early in the function this is, either clean up what
>> > little you need to and then abort early, or jump to your end-of-function
>> > cleanup point. Halfway through the function, you may need to dynamically
>> > allocate more resources, and if at that point you run out, again, you
>> > jump to your late bailout point. At this bailout point, you check which
>> > resources you have opened, and release them.
>> > This way, you have one block of early aborts, nicely maintainably kept
>> > together; one late exit, with the necessary release functions; and
>> > _perhaps_ one or two jumps to that late bailout. In most cases by far,
>> > you'll be able to make those jumps consist of breaks instead of gotos.
>>
>> OK, and what you describe sounds to me like a good style. But what's
>> actually _wrong_ with just using goto for those jumps instead of break?
>> I mean, who are we kidding?
>
> What's wrong is that the goto could go anywhere, while the break can

It could? Wow. It would make the program pretty unpredictable. I wonder
how all the assembly code I wrote years ago worked with their jmp
instructions?


> only go to the end of the loop. What's more, the goto could come from[1]
> anywhere, as well. Sure, well-written code does not use goto like that,
> but if you don't use it when you don't need it, you don't have to worry
> about it. Possibly more importantly, neither does anyone else who reads
> your code.
>
> Richard
>
> [1] Just be grateful C was designed by dmr, and not by Lyon and Woods.
> Our code would be full of twisty little COME FROMs, all alike.

--

Chris Dollin

unread,
Jul 6, 2009, 10:35:11 AM7/6/09
to
Richard wrote:

> ral...@xs4all.nl (Richard Bos) writes:
>
>> Ben C <spam...@spam.eggs> wrote:
>>
>>> On 2009-07-05, Richard Bos <ral...@xs4all.nl> wrote:
>>> > _First_ you check everything that you can check, such as arguments, and
>>> > abort early if anything is wrong. That done, you allocate resources, and
>>> > depending on how early in the function this is, either clean up what
>>> > little you need to and then abort early, or jump to your end-of-function
>>> > cleanup point. Halfway through the function, you may need to dynamically
>>> > allocate more resources, and if at that point you run out, again, you
>>> > jump to your late bailout point. At this bailout point, you check which
>>> > resources you have opened, and release them.
>>> > This way, you have one block of early aborts, nicely maintainably kept
>>> > together; one late exit, with the necessary release functions; and
>>> > _perhaps_ one or two jumps to that late bailout. In most cases by far,
>>> > you'll be able to make those jumps consist of breaks instead of gotos.
>>>
>>> OK, and what you describe sounds to me like a good style. But what's
>>> actually _wrong_ with just using goto for those jumps instead of break?
>>> I mean, who are we kidding?
>>
>> What's wrong is that the goto could go anywhere, while the break can
>
> It could? Wow. It would make the program pretty unpredictable.

Yes. The control flow is no longer encoded in the syntactic structure;
you have to consult the meanings of identifiers.

> I wonder how all the assembly code I wrote years ago worked with their jmp
> instructions?

I expect you were extremely disciplined. In assembler even more so than C,
a jmp instruction can end up /anywhere/ in your code; it's not even confined
to a single function. Most jmp instructions jump to the /same/ point
each time, of course, so you can recover the control structure from
the labels-and-branches; but it's not explicit in the syntax of the
language; it's not /predictable/, although of course it's /discoverable/.
Usually.

--
"It does not need to take events in their correct order." /Hexwood/

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

John Bode

unread,
Jul 6, 2009, 2:11:21 PM7/6/09
to
On Jul 5, 4:01 pm, Ben C <spams...@spam.eggs> wrote:

[snip]

>
> OK, and what you describe sounds to me like a good style. But what's
> actually _wrong_ with just using goto for those jumps instead of break?
> I mean, who are we kidding?

The goto itself isn't the problem so much as the presence of the
label. Whenever I see a naked label in code (as in, not part of a
switch statement), I groan a little inside because now I have to
account for all the corresponding gotos. You may be using them in a
perfectly disciplined manner (branching one direction only, not
bypassing other control structures), but I won't know that until I've
thoroughly inspected the entire function.

It just makes debugging by inspection that much harder. Assume the
following code snippet:

...
i = foo(x);
label:
printf("i=%d\n", i);
...

What value gets printed for i? When does it get printed? Until I
account for every instance of "goto label;", I can't be sure of either
answer.

Keith Thompson

unread,
Jul 6, 2009, 2:28:24 PM7/6/09
to

Of course, the smaller your functions are, the less of a problem
this is.

On the other hand, I'm not sure I'd argue that making gotos easier
to use is the best argument for keeping functions small.

IMHO, most legitimate uses of gotos are substitutes for missing
language features, most commonly either exception handling or
multi-level break. Note that both of these uses require only
forward-branching gotos.

Another possible use for gotos is in implementing finite-state
machines, where a goto really does reflect something happening in
the thing being modeled by the code. But there are other ways of
implementing FSMs.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Richard Bos

unread,
Jul 6, 2009, 2:56:09 PM7/6/09
to
Richard <rgr...@gmail.com> wrote:

> ral...@xs4all.nl (Richard Bos) writes:
> > Ben C <spam...@spam.eggs> wrote:
> >
> >> OK, and what you describe sounds to me like a good style. But what's
> >> actually _wrong_ with just using goto for those jumps instead of break?
> >> I mean, who are we kidding?
> >
> > What's wrong is that the goto could go anywhere, while the break can
>
> It could? Wow. It would make the program pretty unpredictable. I wonder
> how all the assembly code I wrote years ago worked with their jmp
> instructions?

Yes, Devlin, we know you're an imbecile. No need to underscore it.

Richard

Ben C

unread,
Jul 6, 2009, 4:47:47 PM7/6/09
to
On 2009-07-06, Keith Thompson <ks...@mib.org> wrote:
[...]

> IMHO, most legitimate uses of gotos are substitutes for missing
> language features, most commonly either exception handling or
> multi-level break. Note that both of these uses require only
> forward-branching gotos.

That's a very good point. I guess the reason we don't need
backward-branching gotos is because C isn't missing any looping
constructs.

Richard Tobin

unread,
Jul 6, 2009, 5:14:17 PM7/6/09
to
In article <lnprcd3...@nuthaus.mib.org>,
Keith Thompson <ks...@mib.org> wrote:

>IMHO, most legitimate uses of gotos are substitutes for missing
>language features, most commonly either exception handling or
>multi-level break. Note that both of these uses require only
>forward-branching gotos.

One missing language feature that is naturally simulated with a
backward branch is tail recursion optimisation.

-- Richard
--
Please remember to mention me / in tapes you leave behind.

Ben C

unread,
Jul 6, 2009, 5:08:45 PM7/6/09
to
On 2009-07-06, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
> In article <lnprcd3...@nuthaus.mib.org>,
> Keith Thompson <ks...@mib.org> wrote:
>
>>IMHO, most legitimate uses of gotos are substitutes for missing
>>language features, most commonly either exception handling or
>>multi-level break. Note that both of these uses require only
>>forward-branching gotos.
>
> One missing language feature that is naturally simulated with a
> backward branch is tail recursion optimisation.

But who needs tail recursion when you've got loops?

But still I am intrigued, what are you doing here, basically just
goto-ing the top of the function again in order to "recurse"?

Keith Thompson

unread,
Jul 6, 2009, 6:12:23 PM7/6/09
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <lnprcd3...@nuthaus.mib.org>,
> Keith Thompson <ks...@mib.org> wrote:
>
>>IMHO, most legitimate uses of gotos are substitutes for missing
>>language features, most commonly either exception handling or
>>multi-level break. Note that both of these uses require only
>>forward-branching gotos.
>
> One missing language feature that is naturally simulated with a
> backward branch is tail recursion optimisation.

In most cases, loops work nicely for that as well.

Kaz Kylheku

unread,
Jul 6, 2009, 7:09:46 PM7/6/09
to
On 2009-07-06, Ben C <spam...@spam.eggs> wrote:
> On 2009-07-06, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
>> In article <lnprcd3...@nuthaus.mib.org>,
>> Keith Thompson <ks...@mib.org> wrote:
>>
>>>IMHO, most legitimate uses of gotos are substitutes for missing
>>>language features, most commonly either exception handling or
>>>multi-level break. Note that both of these uses require only
>>>forward-branching gotos.
>>
>> One missing language feature that is naturally simulated with a
>> backward branch is tail recursion optimisation.
>
> But who needs tail recursion when you've got loops?

Sufficiently advanced tail recursion can work across functions, and even across
compilation units. Looping is confined to a block of code.

> But still I am intrigued, what are you doing here, basically just
> goto-ing the top of the function again in order to "recurse"?

Under tail recursion, you are making a call which cannot return. Therefore, the
caller's local variables have no next use, and their memory can be purged prior
to the call.

A straightforward tail recursion to the same function is basically equivalent
to /assigning/ new values to the parameters, and branching backwards.

So for instance a the loop for (i = 0; i < 100; i++) stmt; goes something like:

void forloop(int i, int n)
{
if (i < n) { // guard
stmt;
forloop(i + 1, n); // increment and branch backwards
}
}

// ...

forloop(0, 100);

This can be turned into the code:

void forloop(int i, int n)
{
label:
if (i < n) { // guard
stmt;

i = i + 1; // set up the new parameters
n = n; // <- likely optimized away
goto label; // pass the control
}
}

In Lisp, I have experimented with parametrized goto, which then became portable
tail recursion. (Search the comp.lang.lisp archives for "argtags").

The idea is this. Suppose that goto labels could have parameters: the names of
existing variables. And supose that goto could supply argument values. Then you
could write the above like this:

label(i, n): // all names in brackets must be declared variables
// ...
goto label(i + 1, n);

And perhaps the need for the goto could disappear into the syntax also:

label(i, n):
// ...
label(i + 1, n);

Now this simple syntactic sugar almost looks like function calls.

It's a useful extra discipline in the goto. The problem with many uses of goto
is that they don't make it clear what state changes are relevant. It's the
assignments that are the problem. We are puzzled by a backward goto because we
don't know what is different the second and subsequent time around the same
block. Above we know that what is different is that i is incrementing by one.

Suppose that, further, we take on the discipline that we will avoid assignments
in the code. Suppose that all assignments are disguised using the the
label(arg, ...) syntax. Then the gotos become much easier to understand.

You know which variables are pertinent to a basic block headed by a label, and
whow they change. Each parametrized goto explicitly spells out values for every
single one of those variables used in that basic block, even the ones that
don't change, like n above. All of the arguments are required, so you can't
miss anything; you must specify what happens to every darn thing. Moreover, you
can quickly scan a block of code to see whether it depends on any variables
that are not mentioned in its preceding label; they can be added to the label,
and then you can reason about all of the goto places which reach that label:
how should they compute the value of that variable? Which ones should leave the
variable alone, and which ones should change it? So you're not left wondering
``what is the purpose of this i = 42 assignment here, and how does it affect
the previous code after some backward branch is taken''.

Arguably, it's the state change in imperative programming which is the real
cuprit, not goto. Eliminate the assignment and it all starts to look
functional.

Richard Harter

unread,
Jul 7, 2009, 12:50:30 AM7/7/09
to
On Mon, 06 Jul 2009 11:28:24 -0700, Keith Thompson <ks...@mib.org>
wrote:

>John Bode <jfbod...@gmail.com> writes:
>> On Jul 5, 4:01�pm, Ben C <spams...@spam.eggs> wrote:
>>
[snip]

>IMHO, most legitimate uses of gotos are substitutes for missing


>language features, most commonly either exception handling or
>multi-level break. Note that both of these uses require only
>forward-branching gotos.
>
>Another possible use for gotos is in implementing finite-state
>machines, where a goto really does reflect something happening in
>the thing being modeled by the code. But there are other ways of
>implementing FSMs.

One way of looking at the issue is that there are viable and quite
effective ways of programming that are not particularly compatible
with C. Sometimes it is not simply a matter of a missing language
feature; rather we are dealing with features that are alien to C.
For example (syntax and theory off the top of my head) consider the
return_via. It looks something like this:

A(/* args */)
{
/* some code */
return_via B(/* args */);
}

When A is called it gets a return address from its caller; when it
does a return_via it passes (back stage) its return address to B.
If B executes another return_via it passes the return address it
was given to the function it returns via.

Then there are closures and tail-recursion optimization. There is
no decent way in C to do suspend and resume; one can fake
coroutines but it' hackish. C is not consistent with data flow
programming. Usw.

The goto can be used to simulate some of these features; even so,
it is not sufficient because of C's lack of internal procedures.
The upshot is that the goto is not needed in C; there is no
significant room for the goto in doing things the C way.


Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
If I do not see as far as others, it is because
I stand in the footprints of giants.

io_x

unread,
Jul 8, 2009, 2:32:43 PM7/8/09
to

"Richard Bos" <ral...@xs4all.nl> ha scritto nel messaggio
news:4a51d4e1...@news.xs4all.nl...

> What's wrong is that the goto could go anywhere, while the break can

so my code have the freedom to go anywhere, and do everyting

io_x

unread,
Jul 8, 2009, 2:32:37 PM7/8/09
to

"Richard" <rgr...@gmail.com> ha scritto nel messaggio
news:h2st70$v8m$5...@news.eternal-september.org...

> ral...@xs4all.nl (Richard Bos) writes:
>
>> Ben C <spam...@spam.eggs> wrote:
>>
>> What's wrong is that the goto could go anywhere, while the break can
>
> It could? Wow. It would make the program pretty unpredictable. I wonder
> how all the assembly code I wrote years ago worked with their jmp
> instructions?

goto and jumps *inside* one function are not so wrong and makers of errors
like almost all you suggest

Tim Rentsch

unread,
Jul 8, 2009, 2:39:33 PM7/8/09
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <lnprcd3...@nuthaus.mib.org>,
> Keith Thompson <ks...@mib.org> wrote:
>
> >IMHO, most legitimate uses of gotos are substitutes for missing
> >language features, most commonly either exception handling or
> >multi-level break. Note that both of these uses require only
> >forward-branching gotos.
>
> One missing language feature that is naturally simulated with a
> backward branch is tail recursion optimisation.

This is more a Quality of Implementation question than a
language feature question. Some current C compilers
(for example, gcc) alreay do tail-recursion elimination.

Tim Rentsch

unread,
Jul 8, 2009, 3:41:31 PM7/8/09
to
c...@tiac.net (Richard Harter) writes:

Semantically this is the same as 'return B(/*args*);' (not
counting the one case caused by C not allowing (void) values
in return statements, which could easily be fixed). Like
tail recursion optimization, it seems better to take this
as a QOI issue than a language feature issue, especially
since the Standard does not address questions of performance
or optimization.

Richard Tobin

unread,
Jul 8, 2009, 8:12:10 PM7/8/09
to
In article <kfnab3f...@alumnus.caltech.edu>,
Tim Rentsch <t...@alumnus.caltech.edu> wrote:

>> One missing language feature that is naturally simulated with a
>> backward branch is tail recursion optimisation.

>This is more a Quality of Implementation question than a
>language feature question. Some current C compilers
>(for example, gcc) alreay do tail-recursion elimination.

That it's a quality-of-implementation issue is a language
feature. In Scheme it's not a quality-of-implementation
issue, because the standard requires it.

It's useful that some compilers provide it. But unless you
restrict yourself to those compilers, you can't write code
that relies on its availability.

Or to put it another way, the missing language feature is
*required* TRO.

Tim Rentsch

unread,
Jul 9, 2009, 6:24:27 AM7/9/09
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <kfnab3f...@alumnus.caltech.edu>,
> Tim Rentsch <t...@alumnus.caltech.edu> wrote:
>
> >> One missing language feature that is naturally simulated with a
> >> backward branch is tail recursion optimisation.
>
> >This is more a Quality of Implementation question than a
> >language feature question. Some current C compilers
> >(for example, gcc) alreay do tail-recursion elimination.
>
> That it's a quality-of-implementation issue is a language
> feature. In Scheme it's not a quality-of-implementation
> issue, because the standard requires it.

The phrasing is a little bit funny, but I agree with the spirit
expressed here. It's more a QOI question /in C/ because of how
the Standard approaches questions of semantics and optimization;
other language definitions do indeed take different approaches.


> It's useful that some compilers provide it. But unless you
> restrict yourself to those compilers, you can't write code
> that relies on its availability.
>
> Or to put it another way, the missing language feature is
> *required* TRO.

Tail recursion optimization isn't a feature of the language (more
specifically the C language), it's a feature of how it's compiled.
The actual language, in particular its syntax and semantics, would
not be affected by requiring TRO; only implementations would be
affected.

As to the higher level question, I think of this partly (or
mostly?) in terms of the pragmatics. I think it will be easier,
and adoption will happen faster, if adding TRO is "sold" to
implementors as a QOI issue than by trying to convice the ISO
committee to add it to the Standard. Needless to say, I could be
wrong about that, but for now that is my view on how best to make
progress on this front.

Richard Tobin

unread,
Jul 9, 2009, 8:55:26 AM7/9/09
to
In article <kfn1voq...@alumnus.caltech.edu>,
Tim Rentsch <t...@alumnus.caltech.edu> wrote:

>Tail recursion optimization isn't a feature of the language (more
>specifically the C language), it's a feature of how it's compiled.
>The actual language, in particular its syntax and semantics, would
>not be affected by requiring TRO; only implementations would be
>affected.

Would you say that the standard's minimum implementation limits are
not a feature of the language either? Requiring TRO guarantees that
certain programs will work[1] which might have failed otherwise; that
seems like a language feature to me. It changes how you can write
reliable programs.

(In case it's not obvious, "requiring TRO" is shorthand for requiring
that there not be limits on the depth of certain types of recursion;
not on how that is achieved by the implementation.)

[1] Of course they might fail for some other reason.

Richard Bos

unread,
Jul 10, 2009, 5:32:33 PM7/10/09
to
"io_x" <a...@b.c.invalid> wrote:

> "Richard Bos" <ral...@xs4all.nl> ha scritto nel messaggio

> > What's wrong is that the goto could go anywhere, while the break can
>
> so my code have the freedom to go anywhere, and do everyting

Much like a rabid bull, yes. You know what they do with rabid animals,
don't you?

Richard

Tim Rentsch

unread,
Jul 11, 2009, 6:24:55 AM7/11/09
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <kfn1voq...@alumnus.caltech.edu>,
> Tim Rentsch <t...@alumnus.caltech.edu> wrote:
>
> >Tail recursion optimization isn't a feature of the language (more
> >specifically the C language), it's a feature of how it's compiled.
> >The actual language, in particular its syntax and semantics, would
> >not be affected by requiring TRO; only implementations would be
> >affected.
>
> Would you say that the standard's minimum implementation limits are
> not a feature of the language either?

The Standard does two things: it describes the C language, and
it states requirements for what may be considered "conforming
implementations" of language translators. There isn't always a
clear distinction made between the two kinds of statements, but
in most cases it's fairly easy to identify a particular statement
as being one or the other.

My view about minimum implementation limits is that they are
statements of requirements on implementations, and not statements
describing what is (or is not) part of the C language. I think
this view is supported both by how the Standard talks about
programs and by what most developers mean by "programming in C".
For example, consider the following source text:

int foo[ 100000 ];
int main(void){ return 0; }

I think this is a C program. Furthermore I think most C developers
would say it's a C program. And, even though it isn't a 'strictly
conforming program', it does qualify as a 'conforming program' as
far as the Standard is concerned. So I don't think the minimum
implementation limits affect the language per se.


> Requiring TRO guarantees that
> certain programs will work[1] which might have failed otherwise; that
> seems like a language feature to me.

It doesn't affect whether a given source text is legal, or what that
source text means in terms of program semantics; in that sense the
language is unchanged. What it does change is requirements on how
well implementations must do in compiling certain function calls.
To me that seems more like an aspect (or feature) of implementations
than of the language.


> It changes how you can write reliable programs.

No, I don't think it does, because I can write such reliable
programs in C today. It only changes how widely portable those
reliable programs would be.


> (In case it's not obvious, "requiring TRO" is shorthand for requiring
> that there not be limits on the depth of certain types of recursion;
> not on how that is achieved by the implementation.)
>
> [1] Of course they might fail for some other reason.

In general questions about whether a program will execute
successfully are treated by the Standard as Quality of
Implementation issues rather than language issues. Perhaps
that's a good choice, perhaps it isn't, but that's the path that
was chosen. Given that choice, it's very difficult to put a TRO
requirement that really means anything into the Standard as it
currently stands, since almost any program can fail at the whim
of an uncooperative (but still conforming) implementation. I
sympathize with your position, because it does seem desirable to
guarantee certains kinds of execution behavior for certain
language constructs; but, given how the Standard has chosen
to approach this question more generally, in that context it
seems more fruitful to see this as an implementation concern
than as a language issue.

io_x

unread,
Jul 12, 2009, 4:36:51 AM7/12/09
to
Buon Giorno C people

"Richard Bos" <ral...@xs4all.nl> ha scritto nel messaggio

news:4a578b8e...@news.xs4all.nl...

with the prhase above you say "while", "for" etc are better than gotos?
the routines with rabid, with gotos is worse that the one with
loop key words "while", "for", "do while"?

it is some time that i use 80%times "if() goto" and "goto" in C\C++
for loops in my little routines (and macro abbreviations for language key
words).
all seems very good readable too. i don't understand where is the problem
other than the eyes of other are not much accustom for that.

But i have a big ego so can choose what really run right, not blindily
all of what people say: it is right.

The freedom is good because there are problems
that can be resolved only use freedom, it is good if someone can use that
good, but it is difficult because there are chances that can be use wrong.
I hope that my is not that case :)

> Richard

Nick Keighley

unread,
Jul 12, 2009, 7:28:45 AM7/12/09
to
On 28 June, 21:53, Stephen Sprunk <step...@sprunk.org> wrote:
> BartC wrote:

> > I'd also like to know what dynamic language would free resources such as
> > files, windows, and network connections on return from a function.
> > Especially if the purpose of the function was to create such a resource.
>
> If the file, window, or network connection was encapsulated in an
> object, then the destructor for that object would naturally do the
> freeing.  If the function returns the object (or a reference to it,
> depending on the language), the object would obviously not be
> garbage-collected at that point.

so C++ is a "dynamic language"?

Ben C

unread,
Jul 14, 2009, 10:40:11 AM7/14/09
to

And also almost like for loops :) Although I take the point you can do
this across functions.

> It's a useful extra discipline in the goto. The problem with many uses
> of goto is that they don't make it clear what state changes are
> relevant. It's the assignments that are the problem. We are puzzled by
> a backward goto because we don't know what is different the second and
> subsequent time around the same block.

Yes I think that's right. But wouldn't it be simpler just to demand that
compilers optimize tail recursion, as some do anyway, and then just
write recursive code in the normal way?

Or, simpler still, not demand that and just stop wanting optimized tail
recursion in C and use the more idiomatic alternative (loops) instead.

> Above we know that what is different is that i is incrementing by one.
>
> Suppose that, further, we take on the discipline that we will avoid
> assignments in the code. Suppose that all assignments are disguised
> using the the label(arg, ...) syntax. Then the gotos become much
> easier to understand.
>
> You know which variables are pertinent to a basic block headed by a
> label, and whow they change. Each parametrized goto explicitly spells
> out values for every single one of those variables used in that basic
> block, even the ones that don't change, like n above. All of the
> arguments are required, so you can't miss anything; you must specify
> what happens to every darn thing. Moreover, you can quickly scan a
> block of code to see whether it depends on any variables that are not
> mentioned in its preceding label; they can be added to the label, and
> then you can reason about all of the goto places which reach that
> label: how should they compute the value of that variable? Which ones
> should leave the variable alone, and which ones should change it? So
> you're not left wondering ``what is the purpose of this i = 42
> assignment here, and how does it affect the previous code after some
> backward branch is taken''.
>
> Arguably, it's the state change in imperative programming which is the
> real cuprit, not goto. Eliminate the assignment and it all starts to
> look functional.

Well, this would be an interesting way to do things, and you could
implement it fairly easily with a little preprocessor on top of C.

Nobody

unread,
Jul 14, 2009, 5:09:58 PM7/14/09
to
On Tue, 14 Jul 2009 09:40:11 -0500, Ben C wrote:

> Or, simpler still, not demand that and just stop wanting optimized tail
> recursion in C and use the more idiomatic alternative (loops) instead.

That's a PITA with branched recursion.

Tail recursion optimisation is still useful with branched recursion. It's
common to make the last branch the one which is expected to be the
longest; e.g. for tree-search, try the children in order of increasing
number of grandchildren.

Ben C

unread,
Jul 14, 2009, 5:38:52 PM7/14/09
to

OK, now I'm confused. To search a general tree with recursion don't you
always need proper recursion (i.e. as opposed to just tail recursion)?

Nobody

unread,
Jul 15, 2009, 5:13:16 AM7/15/09
to
On Tue, 14 Jul 2009 16:38:52 -0500, Ben C wrote:

>>> Or, simpler still, not demand that and just stop wanting optimized tail
>>> recursion in C and use the more idiomatic alternative (loops) instead.
>>
>> That's a PITA with branched recursion.
>>
>> Tail recursion optimisation is still useful with branched recursion. It's
>> common to make the last branch the one which is expected to be the
>> longest; e.g. for tree-search, try the children in order of increasing
>> number of grandchildren.
>
> OK, now I'm confused. To search a general tree with recursion don't you
> always need proper recursion (i.e. as opposed to just tail recursion)?

You can't just turn it into a loop (without maintaining an explicit
stack), but it's often still useful to optimise the final recursion.

E.g. if you have:

void walk(struct node *node)
{
walk(node->left);
walk(node->right);
}

it may help to turn it into:

void walk(struct node *node)
{
start:
walk(node->left);
node = node->right;
goto start;
}

This won't help if the branches are balanced, but if they aren't, and you
can estimate the relative sizes of the branches, then making the largest
branch an optimised tail-call will minimise the stack usage.

E.g. Lisp's lists are binary trees (the individual elements can themselves
be lists), but they're usually heavily unbalanced. The right branch (the
tail of the list) is usually longer than the left branch (the element). If
you perform tail-call optimisation on the right branch, so you iterate
over the list while recursing into the elements, the stack usage is
proportional to the worst-case nesting depth and independent of the length
of any list.

Ben C

unread,
Jul 15, 2009, 4:36:04 PM7/15/09
to

Thanks for the explanation.

io_x

unread,
Jul 16, 2009, 12:29:12 AM7/16/09
to

"Tim Streater" <timst...@waitrose.com> ha scritto nel messaggio
news:timstreater-C248...@news.individual.net...
> In article <slrnh419uv....@bowser.marioworld>,
> Ben C <spam...@spam.eggs> wrote:
>
>> On 2009-06-23, Tim Streater <timst...@waitrose.com> wrote:
>> > In article <slrnh4123d....@bowser.marioworld>,
>> > Ben C <spam...@spam.eggs> wrote:
>> >
>> >> On 2009-06-22, Jamie <nos...@geniegate.com> wrote:
>> >> [...]
>> >> > One way a layman can judge code quality is (IMO) counting the number of
>> >> > if's in
>> >> > any given block.
>> >>
>> >> Not just laymen, nor just in your opinion.
>> >>
>> >> http://en.wikipedia.org/wiki/Cyclomatic_complexity
>> >>
>> >> > Even if you don't know much about programming, you can get a
>> >> > pretty good view of someones code by just examining how many convoluted,
>> >> > nested if blocks it has.

yesterday i wrote one routine, so you can examine that:

#define R return
#define G goto

int getStdI(char* tmp, int sztmp)
{int i, r, c;
char *a;
if(tmp==0||sztmp<=1)
R 0;
*tmp=0; c=0;
looperr: ;
Fflush_m(stdout_m);
i=fgets_m(tmp, sztmp, stdin_m); // i=strlen(tmp)
if(i<=0) G mostra; // errore di input
if(i+1==sztmp)
{mostra: ;
if(++c>=3) R 0;
P("Stringa Troppo lunga o Errore hardware\nReinserire > ");
Fflush_m(stdin_m);
G looperr;
}
a=tmp+i; r=i; G label;
abbrevia: ;
*a=0; --r;
label: ;
if(a<=tmp) R r;
--a;
if(*a==10) G abbrevia;
else if(*a==13) G abbrevia;
else if(Isspace_m(*a)) G abbrevia;
R r;
}

i'm interessed too how you write a function that do the same
without goto...
for the one that like to speak of UB
here "Fflush_m(stdin_m)" == "clear all buffer for stdin"
the next read is ask from the keyboard

>> >> Unfortunately another coding shibboleth is that early returns and gotos
>> >> are evil. This tends to lead to a lot of nested if blocks.
>> >
>> > Early returns are good and reduce complexity a lot. I haven't needed to
>> > use a GOTO since 1983.
>>
>> Best way in C programming to do early-returns-with-cleanup in my
>> opinion. Yes avoid it for general control flow (the usual loops, if, and
>> switch are much better).
> In fact, I hadn't *willingly* used a goto since 1978, when I stopped
> writing FORTRAN. From then until 1983 or so, I sometimes has to use
> Pascal - with no return statement available. To simulate this, I just
> added a 999 label at the end of procedures and then just did a goto 999.
>
> I'm certainly not going to avoid the return statement when inevitably
> the alternative is if's nested 20 deep or whatever. That just gives you
> an impenetrable and unmaintainable mess.
>
> --
> Tim
>
> "That excessive bail ought not to be required, nor excessive fines imposed,
> nor cruel and unusual punishments inflicted" -- Bill of Rights 1689


Richard Heathfield

unread,
Jul 16, 2009, 5:52:48 AM7/16/09
to
io_x said:

>
> "Tim Streater" <timst...@waitrose.com> ha scritto nel messaggio
> news:timstreater-C248...@news.individual.net...

<snip>

>>> >> > Even if you don't know much about programming, you can get
>>> >> > a pretty good view of someones code by just examining how
>>> >> > many convoluted, nested if blocks it has.
>
> yesterday i wrote one routine, so you can examine that:
>
> #define R return

That's your first mistake.

<more mistakes snipped>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Forged article? See
http://www.cpax.org.uk/prg/usenet/comp.lang.c/msgauth.php
"Usenet is a strange place" - dmr 29 July 1999

io_x

unread,
Jul 16, 2009, 5:55:04 AM7/16/09
to

"io_x" <a...@b.c.invalid> ha scritto nel messaggio
news:4a5eab30$0$1105$4faf...@reader3.news.tin.it...

> yesterday i wrote one routine, so you can examine that:
>
> #define R return
> #define G goto
>
> int getStdI(char* tmp, int sztmp)
> {int i, r, c;
> char *a;
> if(tmp==0||sztmp<=1)
> R 0;
> *tmp=0; c=0;
> looperr: ;
> Fflush_m(stdout_m);
> i=fgets_m(tmp, sztmp, stdin_m); // i=strlen(tmp)
> if(i<=0) G mostra; // errore di input
> if(i+1==sztmp)
> {mostra: ;
> if(++c>=3) R 0;
> P("Stringa Troppo lunga o Errore hardware\nReinserire > ");
> Fflush_m(stdin_m);
> G looperr;

i have done some little change, it has to return -1 for error
because it is possible too to enter a string of len == 0

// Prende una stringa di lunghezza massima sztmp-1 chars
// dal puntatore di file fi, mostra gli errori in fo
// se -1 errore
// altrimenti presa, senza errori, una stringa di lunghezza
// quello che ritorna
// NB: alla fine vengono eliminati \r\n e tutti gli spazi
int get(char* tmp, int sztmp, FILE_m* fi, FILE_m* fo)


{int i, r, c;
char *a;

if(tmp==0||sztmp<=1||fi==0||fo==0)
R -1;
*tmp=0; c=0;
looperr: ;
Fflush_m(fo);
i=fgets_m(tmp, sztmp, fi);


if(i<=0) G mostra; // errore di input

if(i+1==sztmp) // i=len(tmp)
{mostra: ;
if(++c>=3) R -1;
Pf_m(fo, "Stringa Troppo lunga o Errore hardware\nReinserire > ");
Fflush_m(fi);


G looperr;
}
a=tmp+i; r=i; G label;
abbrevia: ;
*a=0; --r;
label: ;
if(a<=tmp) R r;
--a;
if(*a==10) G abbrevia;
else if(*a==13) G abbrevia;
else if(Isspace_m(*a)) G abbrevia;
R r;
}

int getStdI(char* tmp, int sztmp)
{R get(tmp, sztmp, stdin_m, stdout_m);}

Keith Thompson

unread,
Jul 16, 2009, 11:41:39 AM7/16/09
to
"io_x" <a...@b.c.invalid> writes:
[...]

> #define R return
> #define G goto
[...]

Why do you define silly macros like these?

Flash Gordon

unread,
Jul 16, 2009, 1:27:06 PM7/16/09
to
Keith Thompson wrote:
> "io_x" <a...@b.c.invalid> writes:
> [...]
>> #define R return
>> #define G goto
> [...]
>
> Why do you define silly macros like these?

Why bother asking? It's almost certainly the same person who has been
here a few times before using those stupid macros. Better to ignore him/her.
--
Flash Gordon

Richard Bos

unread,
Jul 16, 2009, 2:58:51 PM7/16/09
to
Keith Thompson <ks...@mib.org> wrote:

> "io_x" <a...@b.c.invalid> writes:
> [...]
> > #define R return
> > #define G goto
> [...]
>
> Why do you define silly macros like these?

Why do you expect a sensible answer from silly posters like these?

Richard

Keith Thompson

unread,
Jul 16, 2009, 3:01:59 PM7/16/09
to

I don't, but I'm always prepared to be pleasantly surprised.

(Yes, I should have ignored it.)

Richard Harter

unread,
Jul 16, 2009, 3:23:13 PM7/16/09
to
On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:

>
[snip]

The first step is to convert it into a readable format. Most of the CLC
regulars cannot get beyond the first thing that offends their delicate
sensibilities. The following is a reformatting with the R and G macros
stripped out, comments converted to /**/ (// is legal in C99 but can cause
trouble in postings), and an attempt has been made to put decent white
space in. I hope this is a better starting point for anyone who might want
to recode to remove the gotos. Incidentally, the code reminds me of stream
of consciousness code done in FORTRAN 66.

int getStdI(char *tmp, int sztmp)
{
int i, r, c;
char *a;

if(tmp==0||sztmp<=1) return 0;
*tmp=0; c=0;

looperr: ;
Fflush_m(stdout_m);
i=fgets_m(tmp, sztmp, stdin_m); /* i=strlen(tmp) */
if(i<=0) goto mostra; /* errore di input */
if(i+1==sztmp) {
mostra: ;
if(++c>=3) return 0;
P("Stringa Troppo lunga o Errore hardware\nreturneinserire > ");
Fflush_m(stdin_m);
goto looperr;
}
a=tmp+i; r=i;
goto label;
abbrevia: ;
*a=0; --r;
label: ;
if(a<=tmp) return r;
--a;
if(*a==10) goto abbrevia;
else if(*a==13) goto abbrevia;
else if(Isspace_m(*a)) goto abbrevia;
return r;

Richard Harter

unread,
Jul 16, 2009, 3:56:59 PM7/16/09
to
On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:

>yesterday i wrote one routine, so you can examine that:

[snip original code]

Here is a rewrite that eliminates the gotos and the "silly" macros. There
is no guarantee that it (or the original code) is correct. Some people
have a twisted panties problem with do/while blocks. In this case they are
easily recoded and I leave the joy of doing so to anyone who might care.

int getStdI(char* tmp, int sztmp)
{
int i, r, c;
char *a;

if(tmp==0||sztmp<=1) return 0;
*tmp=0; c=0;

do {


Fflush_m(stdout_m);
i=fgets_m(tmp, sztmp, stdin_m); /* i=strlen(tmp) */

if((i<=0) || (i+1==sztmp)) { /* errore di input */
if(++c>=3) return 0;
P("Stringa Troppo lunga o Errore hardware\nreturneinserire > ");
Fflush_m(stdin_m);
continue;
}
} while(0);

a=tmp+i; r=i;
do {
if(a<=tmp) break;
--a;
if (!((*a==10)||(*a==13)||(Isspace_m(*a))) break;
*a=0; --r;
} while(1);

bartc

unread,
Jul 16, 2009, 3:59:09 PM7/16/09
to

"Richard Harter" <c...@tiac.net> wrote in message
news:4a5f7c18...@text.giganews.com...

> On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:

>>#define R return
>>#define G goto

> The first step is to convert it into a readable format. Most of the CLC


> regulars cannot get beyond the first thing that offends their delicate
> sensibilities. The following is a reformatting with the R and G macros
> stripped out,

> goto label;
...
> label: ;

This is still a brilliant piece of coding. What better name for a label?

--
Bart

Richard Harter

unread,
Jul 16, 2009, 4:27:51 PM7/16/09
to

Indeed. It's a pity that one can't use it for all of one's labels.

Keith Thompson

unread,
Jul 16, 2009, 4:44:57 PM7/16/09
to
c...@tiac.net (Richard Harter) writes:
> On Thu, 16 Jul 2009 19:59:09 GMT, "bartc" <ba...@freeuk.com> wrote:
>>"Richard Harter" <c...@tiac.net> wrote in message
>>news:4a5f7c18...@text.giganews.com...
>>> On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:
>>
>>>>#define R return
>>>>#define G goto
>>
>>> The first step is to convert it into a readable format. Most of the CLC
>>> regulars cannot get beyond the first thing that offends their delicate
>>> sensibilities. The following is a reformatting with the R and G macros
>>> stripped out,
>>
>>> goto label;
>>...
>>> label: ;
>>
>>This is still a brilliant piece of coding. What better name for a label?
>
> Indeed. It's a pity that one can't use it for all of one's labels.

Oh, but you can, if you don't have more than one label per function
(which is a good idea anyway).

Ben Bacarisse

unread,
Jul 16, 2009, 4:53:39 PM7/16/09
to
c...@tiac.net (Richard Harter) writes:

> On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:
>
>>yesterday i wrote one routine, so you can examine that:
>
> [snip original code]
>
> Here is a rewrite that eliminates the gotos and the "silly" macros. There
> is no guarantee that it (or the original code) is correct. Some people
> have a twisted panties problem with do/while blocks.

Who? I've never heard an objection to them. I've seen them over-used
(beginners especially seem to prefer the delayed test and this can
lead them into forgetting about a boundary case) but you presumably
mean that some people object when the code is otherwise correct.

> In this case they are
> easily recoded and I leave the joy of doing so to anyone who might care.
>
> int getStdI(char* tmp, int sztmp)
> {
> int i, r, c;
> char *a;
>
> if(tmp==0||sztmp<=1) return 0;
> *tmp=0; c=0;
>
> do {
> Fflush_m(stdout_m);
> i=fgets_m(tmp, sztmp, stdin_m); /* i=strlen(tmp) */
> if((i<=0) || (i+1==sztmp)) { /* errore di input */
> if(++c>=3) return 0;
> P("Stringa Troppo lunga o Errore hardware\nreturneinserire > ");
> Fflush_m(stdin_m);
> continue;

Why continue? There is nothing left in the body and if there were,
surely an else would be the place to put it?

> }
> } while(0);

Eh? I think you intended something like:

do {
Fflush_m(stdout_m);
i=fgets_m(tmp, sztmp, stdin_m); /* i=strlen(tmp) */
if((i<=0) || (i+1==sztmp)) { /* errore di input */
if(++c>=3) return 0;
P("Stringa Troppo lunga o Errore hardware\nreturneinserire > ");
Fflush_m(stdin_m);
}

else break;
} while (1);

and then I'd write while (1) ... rather than do ... while (1). The
"loop 'til I break" idea is better expressed with a while I think.

> a=tmp+i; r=i;
> do {
> if(a<=tmp) break;
> --a;
> if (!((*a==10)||(*a==13)||(Isspace_m(*a))) break;

Missing ).

> *a=0; --r;
> } while(1);

Again why not while (1) here?

> return r;
> }

IMO, the biggest improvement would be to split the two actions into
separate functions. Both has a legitimate use on its own and a
two-line wrapper can combine them.

--
Ben.

Richard Harter

unread,
Jul 16, 2009, 5:27:29 PM7/16/09
to
On Thu, 16 Jul 2009 21:53:39 +0100, Ben Bacarisse <ben.u...@bsb.me.uk>
wrote:

>c...@tiac.net (Richard Harter) writes:
>
>> On Thu, 16 Jul 2009 06:29:12 +0200, "io_x" <a...@b.c.invalid> wrote:
>>
>>>yesterday i wrote one routine, so you can examine that:
>>
>> [snip original code]
>>
>> Here is a rewrite that eliminates the gotos and the "silly" macros. There
>> is no guarantee that it (or the original code) is correct. Some people
>> have a twisted panties problem with do/while blocks.
>
>Who? I've never heard an objection to them. I've seen them over-used
>(beginners especially seem to prefer the delayed test and this can
>lead them into forgetting about a boundary case) but you presumably
>mean that some people object when the code is otherwise correct.

I've seen objections now and then on stylistic and purity of structured
programming grounds. As you point out while(1) and do/while(1) are
equivalent and I should have used them. I plead guilty to doin a more or
less mechanical translation of the original code.

You're right of course. I started with a do/while(0) to get a single block
and didn't think to see if there was something better.

>
>> a=tmp+i; r=i;
>> do {
>> if(a<=tmp) break;
>> --a;
>> if (!((*a==10)||(*a==13)||(Isspace_m(*a))) break;
>
>Missing ).
>
>> *a=0; --r;
>> } while(1);
>
>Again why not while (1) here?
>
>> return r;
>> }
>
>IMO, the biggest improvement would be to split the two actions into
>separate functions. Both has a legitimate use on its own and a
>two-line wrapper can combine them.

Quite possibly. One of the things that is wrong with the original code is
that the code completely obscures the fact the action is a succession of
two simple actions.

Phil Carmody

unread,
Jul 16, 2009, 6:18:10 PM7/16/09
to
Richard Heathfield <r...@see.sig.invalid> writes:
> io_x said:
>> "Tim Streater" <timst...@waitrose.com> ha scritto nel messaggio
>> news:timstreater-C248...@news.individual.net...
> <snip>
>
>>>> >> > Even if you don't know much about programming, you can get
>>>> >> > a pretty good view of someones code by just examining how
>>>> >> > many convoluted, nested if blocks it has.
>>
>> yesterday i wrote one routine, so you can examine that:
>>
>> #define R return
>
> That's your first mistake.

It's not a mistake, it's merely an unconventional coding-style choice
of marginal acceptance. We live in enlightened times, now, Richard,
terms like 'mistake' are no longer appropriate.

Phil
--
If GML was an infant, SGML is the bright youngster far exceeds
expectations and made its parents too proud, but XML is the
drug-addicted gang member who had committed his first murder
before he had sex, which was rape. -- Erik Naggum (1965-2009)

Richard Heathfield

unread,
Jul 16, 2009, 6:36:21 PM7/16/09
to
Phil Carmody said:

> Richard Heathfield <r...@see.sig.invalid> writes:
>> io_x said:
>>> "Tim Streater" <timst...@waitrose.com> ha scritto nel
>>> messaggio
>>> news:timstreater-C248...@news.individual.net...
>> <snip>
>>
>>>>> >> > Even if you don't know much about programming, you can
>>>>> >> > get a pretty good view of someones code by just examining
>>>>> >> > how many convoluted, nested if blocks it has.
>>>
>>> yesterday i wrote one routine, so you can examine that:
>>>
>>> #define R return
>>
>> That's your first mistake.
>
> It's not a mistake, it's merely an unconventional coding-style
> choice of marginal acceptance.

It's a mistake.

> We live in enlightened times, now,

You obviously don't live in the UK. (Or, if you do, you walk around
with your societal eyes closed.) He governs best who governs least,
and the UK parliament governs as much as it possibly can.

> Richard, terms like 'mistake' are no longer appropriate.

I disagree. "Mistake" is precisely the right word for what it is. If
I were marking his exam paper (and yes, I do have (paid!)
experience in marking C programming exam papers), he'd lose a mark
for such a stupid #define.

Richard Harter

unread,
Jul 17, 2009, 12:35:43 AM7/17/09
to
On Thu, 16 Jul 2009 22:36:21 +0000, Richard Heathfield
<r...@see.sig.invalid> wrote:


[snip]

>I disagree. "Mistake" is precisely the right word for what it is. If
>I were marking his exam paper (and yes, I do have (paid!)
>experience in marking C programming exam papers), he'd lose a mark
>for such a stupid #define.

You are entitled to your opinion, such as it is. However it is a mistake.

Richard Heathfield

unread,
Jul 17, 2009, 3:38:08 AM7/17/09
to
Richard Harter said:

> On Thu, 16 Jul 2009 22:36:21 +0000, Richard Heathfield
> <r...@see.sig.invalid> wrote:
>
>
> [snip]
>
>>I disagree. "Mistake" is precisely the right word for what it is.
>>If I were marking his exam paper (and yes, I do have (paid!)
>>experience in marking C programming exam papers), he'd lose a mark
>>for such a stupid #define.
>
> You are entitled to your opinion, such as it is.

Right.

> However it is a mistake.

Right, it's a mistake, which is what I said in the first place. So
we are in agreement. Good.

If, however, you mean that my opinion is mistaken, I disagree, just
as you probably disagree that your grammar is mistaken - the
difference (naturally) being that I'm right and you're wrong. (No
doubt you would say much the same thing, but with the preposition
dereferencing being reversed.)

Ben C

unread,
Jul 17, 2009, 6:32:32 AM7/17/09
to
On 2009-07-16, Richard Heathfield <r...@see.sig.invalid> wrote:
> Phil Carmody said:
>
>> Richard Heathfield <r...@see.sig.invalid> writes:
>>> io_x said:
>>>> "Tim Streater" <timst...@waitrose.com> ha scritto nel
>>>> messaggio
>>>> news:timstreater-C248...@news.individual.net...
>>> <snip>
>>>
>>>>>> >> > Even if you don't know much about programming, you can
>>>>>> >> > get a pretty good view of someones code by just examining
>>>>>> >> > how many convoluted, nested if blocks it has.
>>>>
>>>> yesterday i wrote one routine, so you can examine that:
>>>>
>>>> #define R return
>>>
>>> That's your first mistake.
>>
>> It's not a mistake, it's merely an unconventional coding-style
>> choice of marginal acceptance.
>
> It's a mistake.

I don't like it either, but why's it a mistake as opposed to just
objectionable style?

Richard Heathfield

unread,
Jul 17, 2009, 7:13:06 AM7/17/09
to
Ben C said:

> On 2009-07-16, Richard Heathfield <r...@see.sig.invalid> wrote:
>> Phil Carmody said:
>>

<snip>


>>>
>>> It's not a mistake, it's merely an unconventional coding-style
>>> choice of marginal acceptance.
>>
>> It's a mistake.
>
> I don't like it either, but why's it a mistake as opposed to just
> objectionable style?

Objectionable style /is/ a mistake. :-)

Dik T. Winter

unread,
Jul 17, 2009, 7:45:50 AM7/17/09
to
In article <4a5f8d18...@text.giganews.com> c...@tiac.net (Richard Harter) writes:
...

> >> goto label;
> >...
> >> label: ;
> >
> >This is still a brilliant piece of coding. What better name for a label?
>
> Indeed. It's a pity that one can't use it for all of one's labels.

And all variables ought to be named "variable".
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Richard Harter

unread,
Jul 17, 2009, 10:52:58 AM7/17/09
to
On Fri, 17 Jul 2009 07:38:08 +0000, Richard Heathfield
<r...@see.sig.invalid> wrote:

>Richard Harter said:
>
>> On Thu, 16 Jul 2009 22:36:21 +0000, Richard Heathfield
>> <r...@see.sig.invalid> wrote:
>>
>>
>> [snip]
>>
>>>I disagree. "Mistake" is precisely the right word for what it is.
>>>If I were marking his exam paper (and yes, I do have (paid!)
>>>experience in marking C programming exam papers), he'd lose a mark
>>>for such a stupid #define.
>>
>> You are entitled to your opinion, such as it is.
>
>Right.
>
>> However it is a mistake.
>
>Right, it's a mistake, which is what I said in the first place. So
>we are in agreement. Good.
>
>If, however, you mean that my opinion is mistaken, I disagree, just
>as you probably disagree that your grammar is mistaken - the
>difference (naturally) being that I'm right and you're wrong. (No
>doubt you would say much the same thing, but with the preposition
>dereferencing being reversed.)

Your opinion is both mistaken and a mistake.

Richard Harter

unread,
Jul 17, 2009, 10:55:07 AM7/17/09
to
On Fri, 17 Jul 2009 11:45:50 GMT, "Dik T. Winter" <Dik.W...@cwi.nl>
wrote:

>In article <4a5f8d18...@text.giganews.com> c...@tiac.net (Richard Harter) writes:
>...
> > >> goto label;
> > >...
> > >> label: ;
> > >
> > >This is still a brilliant piece of coding. What better name for a label?
> >
> > Indeed. It's a pity that one can't use it for all of one's labels.
>
>And all variables ought to be named "variable".

An excellent suggestion. Should all programs be named "program" or is that
going too far.

Nick Keighley

unread,
Jul 17, 2009, 11:04:58 AM7/17/09
to
On 16 July, 23:18, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
wrote:

> Richard Heathfield <r...@see.sig.invalid> writes:
> > io_x said:
> >> "Tim Streater" <timstrea...@waitrose.com> ha scritto nel messaggio
> >>news:timstreater-C248...@news.individual.net...

> >>>> >> > Even if you don't know much about programming, you can get


> >>>> >> > a pretty good view of someones code by just examining how
> >>>> >> > many convoluted, nested if blocks it has.
>
> >> yesterday i wrote one routine, so you can examine that:
>
> >> #define  R  return
>
> > That's your first mistake.
>
> It's not a mistake, it's merely an unconventional coding-style choice
> of marginal acceptance. We live in enlightened times, now, Richard,
> terms like 'mistake' are no longer appropriate.

"Programs must be written for people to read, and only
incidentally for machines to execute."
- Abelson & Sussman, Structure and Interpretation of Computer Programs

Richard Heathfield

unread,
Jul 17, 2009, 12:10:27 PM7/17/09
to
Richard Harter said:

<snip>



> Your opinion is both mistaken and a mistake.

You could be right. I certainly don't think for even a moment that
you are... but it's not actually impossible. :-)

Phil Carmody

unread,
Jul 17, 2009, 2:08:09 PM7/17/09
to
c...@tiac.net (Richard Harter) writes:
> On Fri, 17 Jul 2009 11:45:50 GMT, "Dik T. Winter" <Dik.W...@cwi.nl>
> wrote:
>
>>In article <4a5f8d18...@text.giganews.com> c...@tiac.net (Richard Harter) writes:
>>...
>> > >> goto label;
>> > >...
>> > >> label: ;
>> > >
>> > >This is still a brilliant piece of coding. What better name for a label?
>> >
>> > Indeed. It's a pity that one can't use it for all of one's labels.
>>
>>And all variables ought to be named "variable".
>
> An excellent suggestion. Should all programs be named "program" or is that
> going too far.

I think 80% of the programs that I write are called 'crap' and compiled
from /tmp/crap.c . "program"'s just far to verbose for programs like that.

io_x

unread,
Jul 17, 2009, 2:25:47 PM7/17/09
to

"io_x" <a...@b.c.invalid> ha scritto nel messaggio
news:4a5ef790$0$47541$4faf...@reader1.news.tin.it...

>
> "io_x" <a...@b.c.invalid> ha scritto nel messaggio
> news:4a5eab30$0$1105$4faf...@reader3.news.tin.it...
>> yesterday i wrote one routine, so you can examine that:
> i have done some little change, it has to return -1 for error
> because it is possible too to enter a string of len == 0

i change something, what about this for input routine that
get a string from input??

// 0 all ok
// 1 for set ERR
// 2 for set EOF
// 3 ??
int LevaSpaziDalloStream(FILE_m* fi)
{int c;
label: ;
c=Fgetc_m(fi);
if(c==-1)
{lerr: ;
if(ferror_m(fi)) R 1;
else if(feof_m(fi)) R 2;
else R 3;
}
if(c==13||c==10) G lend;
c&=0xFF;
if(Isspace_m(c)) G label;
lend: ;
Ungetc_m(c, fi); if( cf() == 1) G lerr;
R 0;
}

// Prende una stringa di lunghezza massima sztmp-1 chars
// dal puntatore di file fi, mostra gli errori in fo
// se -1 errore

// altrimenti presa, senza errori, una stringa di lunghezza eax
// NB: all'inizio vengono eliminati gli spazi e le tabulazioni;
// alla fine vengono eliminati \r\n e tutti gli spazi
// fino a possibilmente farla diventare stringa nulla se tale e'
// l'input


int get(char* tmp, int sztmp, FILE_m* fi, FILE_m* fo)

{int i, r, c, cf1;


char *a;
if(tmp==0||sztmp<=1||fi==0||fo==0)
R -1;
*tmp=0; c=0;
looperr: ;
Fflush_m(fo);

if( LevaSpaziDalloStream(fi)!=0 ) G laa;
i=getl_m(tmp, sztmp, fi); cf1=cf();
if(i<0){if(cf1==1) // (linea troppo lunga + EOF) o ERR
{laa: ; Pf_m(fo, "\n"); R -1;}


if(++c>=3) R -1;
Pf_m(fo, "Stringa Troppo lunga o Errore hardware\nReinserire > ");

Richard Harter

unread,
Jul 17, 2009, 7:45:37 PM7/17/09
to
On Fri, 17 Jul 2009 16:10:27 +0000, Richard Heathfield
<r...@see.sig.invalid> wrote:

>Richard Harter said:
>
><snip>
>
>> Your opinion is both mistaken and a mistake.
>
>You could be right. I certainly don't think for even a moment that
>you are... but it's not actually impossible. :-)

I am never simply right.

Richard Bos

unread,
Jul 19, 2009, 9:31:50 AM7/19/09
to
Keith Thompson <ks...@mib.org> wrote:

> ral...@xs4all.nl (Richard Bos) writes:
> > Keith Thompson <ks...@mib.org> wrote:
> >> "io_x" <a...@b.c.invalid> writes:
> >> [...]
> >> > #define R return
> >> > #define G goto
> >> [...]
> >>
> >> Why do you define silly macros like these?
> >
> > Why do you expect a sensible answer from silly posters like these?
>
> I don't, but I'm always prepared to be pleasantly surprised.

In theory, I even agree with you, but practice forces me to be cynical.
I rue this, but I cannot help it.

Richard

Richard Bos

unread,
Jul 19, 2009, 9:31:48 AM7/19/09
to
Ben C <spam...@spam.eggs> wrote:

If the style is objectionable enough to become hard to read, it's a
mistake. Sure, clarity, too, is in the eye of the beholder, but I can't
imagine that many people find IOCCC-style easy to read.

Richard

io_x

unread,
Jul 20, 2009, 4:52:30 AM7/20/09
to

"Keith Thompson" <ks...@mib.org> ha scritto nel messaggio
news:lnprc0w...@nuthaus.mib.org...

> ral...@xs4all.nl (Richard Bos) writes:
>> Keith Thompson <ks...@mib.org> wrote:
>>
>>> "io_x" <a...@b.c.invalid> writes:
>>> [...]
>>> > #define R return
>>> > #define G goto
>>> [...]
>>>
>>> Why do you define silly macros like these?
>>
>> Why do you expect a sensible answer from silly posters like these?
>
> I don't, but I'm always prepared to be pleasantly surprised.
>
> (Yes, I should have ignored it.)

i say it again: the key words of one language, for a matter of readability,
have to preserve horizontal space, so they have to be of little length.

the recognise of the key words is not less if i write e.g. " R "
compared with " return " etc

Chris Dollin

unread,
Jul 20, 2009, 5:09:22 AM7/20/09
to
io_x wrote:

> i say it again: the key words of one language, for a matter of readability,
> have to preserve horizontal space,

No, they don't.

> the recognise of the key words is not less if i write e.g. " R "
> compared with " return " etc

Yes, it is.

--
"It does not need to take events in their correct order." /Hexwood/

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

bartc

unread,
Jul 20, 2009, 5:46:54 AM7/20/09
to

"Chris Dollin" <chris....@hp.com> wrote in message
news:h41c6t$jp3$2...@news-pa1.hpl.hp.com...

> io_x wrote:
>
>> i say it again: the key words of one language, for a matter of
>> readability,
>> have to preserve horizontal space,
>
> No, they don't.

ITYM 'N they don't'

>
>> the recognise of the key words is not less if i write e.g. " R "
>> compared with " return " etc
>
> Yes, it is.

IOW 'Y, it is'.

See, it's easy to get the hang of it.

I think io_x (or can I call him i?) needs to program an editor that will do
this compression for him, if his screen is that narrow, leaving the source
code unaltered for everyone else's benefit.

HTH

--
Bartc

It is loading more messages.
0 new messages