char** to {'':('',)}

Tim Peters tim.one at home.com
Fri Aug 31 13:18:35 EDT 2001


[Tim]
> The Python implementation has many examples of this, jumping to an
> error label at the end when things go wrong "in the middle".

[Grant Griffin]
> That's a good reason.  (I've also found gotos quite helpful in
> converting Fortran to C <wink>.)
>
> I can't say I use them much, but I _am_ a big fan of the "almost-goto"
> constructs like return, break, and continue.  In particular, I
> like to do early returns to avoid needless nesting.

Ignacio is hung up on a four-letter word, and is thereby doomed to write
code that's needlessly brittle.  The way goto is used in Python's
implementation is usually a simple by-hand compilation of the higher-level
construct (which can't be coded *directly* in C):

    initialize temps and result to NULL
    try:
        # normal stuff, but when an error occurs, do
        raise error

        # more stuff

    except error:
        Py_XDECREF(result);
        result = NULL;

    Py_XDECREF(temp1);
    ...
    Py_XDECREF(tempn);
    return result;

Look back at the pattern I suggested with gotos, and you'll see that it's
implementing exactly that:

    initialize temps and result to NULL
    # normal stuff, but when an error occurs, do
    goto error;

    # more stuff
    goto normal_return;

error:
    Py_XDECREF(result);
    result = NULL;
    /* fall-through */
normal_return:
    Py_XDECREF(temp1);
    ...
    Py_XDECREF(tempn);
    return result;

It's not the gotos that make this more robust, it's the higher-level
construct they're *implementing*, and that construct is exactly on-target
for preventing "stupid mistakes" in letting temps leak, or letting a partial
result leak in an error case.  If you suffer KFG (Kneejerk Fear of Goto), I
suppose you could do

    initialize temps and result to NULL
    int erroneous = 0;
    do {
        # normal stuff, but when an error occurs, do
        erroneous = 1;
        break;  /* and hope we're breaking out of the 'do'! */

        # more stuff

    } while(0);

    if (erroneous) {
        Py_XDECREF(result);
        result = NULL;
    }
    Py_XDECREF(temp1);
    ...
    Py_XDECREF(tempn);
    return result;

but that's no improvement by any rational measure ...

we-won't-talk-about-python's-use-of-goto-in-the-lexer<wink>-ly y'rs  - tim





More information about the Python-list mailing list