GOTO (was Re: Appeal for python developers)

Anthra Norell anthra.norell at tiscalinet.ch
Sun Mar 6 14:26:12 CET 2005


> Please include "goto" command in future python realeses
> know that proffesional programers doesn't like to use it, 
> but for me as newbie it's too hard to get used replacing it 
> with "while", "def" or other commands
> -- 

I believe the bad reputation of 'goto' goes back to the originators of structured programming and what they meant to say was: don't use goto as a quick fix for a poorly written tangle of looping constructs. It aggravates the tangle when the solution is to straighten it out. Had they deemed 'goto' useless, they would have thrown it out there and then. They didn't, because a policy against misuse that prevents all use runs against the interests of those capable of avoiding the misuse on their own. Typically, elites revolt against dictatorial restrictions. Here, strangely, the elites afflict themselves voluntarily with a sort of gotophobia as a hallmark of professionalism.
      I had a period when I was into state machines and came up with a programming technique that started out with a state table in three columns. This example is a vending machine.

   Current state                        Transition event(s)                Next state(s)

   WAITING FOR ACTION                   customer drops coin                COIN HAS BEEN DROPPED
                                        customer selects beverage          ORDER RECEIVED
                                        customer cancels order             ACCOUNT CLOSURE IS DUE
                                        else                               WAITING FOR ACTION

   COIN HAS BEEN DROPPED                identify coin
                                        credit account                     PAYMENT DUE IS UNKNOWN

   ORDER RECEIVED                       display selection                  PAYMENT DUE IS UNKNOWN

   PAYMENT DUE IS UNKNOWN               no selection made                  NOTHING IS ORDERED
                                        payment is short                   PAYMENT IS SHORT
                                        else                               PAYMENT COVERS

   NOTHING IS ORDERED                   prompt for selection               WAITING FOR ACTION

   PAYMENT IS SHORT                     display balance due
                                        prompt for payment                 WAITING FOR ACTION

   PAYMENT COVERS                       prompt for release action          WAITING FOR RELEASE ACTION

   WAITING FOR RELEASE ACTION           customer activates release         DELIVERY IS DUE
                                        customer drops coin                COIN HAS BEEN DROPPED
                                        customer selects beverage          ORDER_RECEIVED
                                        customer cancels order             ACCOUNT CLOSURE IS DUE
                                        else                               WAITING FOR RELEASE ACTION

   DELIVERY IS DUE                      release beverage                   
                                        debit account                      ACCOUNT CLOSURE IS DUE

   ACCOUNT CLOSURE IS DUE               return account balance             WAITING FOR ACTION


All of the next states reappear, no more than once each, in the first column as current states and so the table is consistent and exhaustive. Consistency is automatic regardless how big a table grows, if every new next state entered is copied right away into the first column where a bunch of them may accumulate, each one conspicuously unhandled as long as it stands alone on its line. Their order is irrelevant. 
      Converting the table into a program is trivial, because the table is a program. A few minor formal edits make it digestible for a C compiler:
 

   WAITING_FOR_ACTION:                  if customer_drops_coin ()          goto COIN_HAS_BEEN_DROPPED;
                                        if customer_selects_beverage ()    goto ORDER_RECEIVED;
                                        if customer_cancels_order ()       goto ACCOUNT_CLOSURE_IS_DUE;
                                                                           goto WAITING_FOR_ACTION;        

   COIN_HAS_BEEN_DROPPED:               identify_coin ();
                                        credit_account ();                 goto PAYMENT_DUE_IS_UNKNOWN;

   ORDER_RECEIVED:                      display_selection ();              goto PAYMENT_DUE_IS_UNKNOWN;

   PAYMENT_DUE_IS_UNKNOWN:              if no_selection_made ()            goto NOTHING_IS_ORDERED;
                                        if payment_is_short ()             goto PAYMENT_IS_SHORT;
                                                                           goto PAYMENT_COVERS;

   NOTHING_IS_ORDERED:                  prompt_for_selection ();           goto WAITING_FOR_ACTION;

   PAYMENT_IS_SHORT:                    display_balance_due ();
                                        prompt_for_balance_due ();         goto WAITING_FOR_ACTION;

   PAYMENT_COVERS:                      prompt_for_release_action ();   // goto WAITING_FOR_RELEASE_ACTION;

   WAITING_FOR_RELEASE_ACTION:          if customer_activates_release ()   goto DELIVERY_IS_DUE;
                                        if customer_drops_coin ()          goto COIN_HAS_BEEN_DROPPED;
                                        if customer_selects_beverage ()    goto ORDER_RECEIVED;
                                        if customer_cancels_order ()       goto ACCOUNT_CLOSURE_IS_DUE;
                                                                           goto WAITING_FOR_RELEASE_ACTION;        

   DELIVERY_IS_DUE:                     release_beverage ();
                                        debit_account ();               // goto ACCOUNT_CLOSURE_IS_DUE;

   ACCOUNT_CLOSURE_IS_DUE:              return_account_balance ();         goto WAITING_FOR_ACTION;


An anachronism? So what? Isn't it simple, elegant, legible, easy to modify and expand and self-documenting on top of it? One advantage of this method is that legibility does not degrade as the complexitiy of the transition paths increases. Conditional loops do become increasingly difficult to follow as they nest and accumulate breaks and state flags, and so modifications become increasingly difficult to make. An upgrade simpler than the following one, on the other hand, is hard to imagine:

   
   COIN_HAS_BEEN_DROPPED:               identify_coin ();
                                        if coin_is_a_dud ()              goto HOLDING_UNWANTED_PROPERTY;   // New
                                        credit_account ();               goto PAYMENT_DUE_IS_UNKNOWN;
                                                                      
   HOLDING_UNWANTED_PROPERTY:           reject_dud ();                                                     // New
                                        /* admonish_customer (); */      goto WAITING_FOR_ACTION;          // New


I used this technique in C and found it useful on some occasions. I did not combine gotos and loops. Not all problems lend themselves to this solution, But some do and that reminds that to judge merit it helps to ignore reputation. 


Frederic

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20050306/b26894c3/attachment.html>


More information about the Python-list mailing list