Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Working around a lack of 'goto' in python

Reply
Thread Tools

Working around a lack of 'goto' in python

 
 
Stephen Horne
Guest
Posts: n/a
 
      03-07-2004
On Sat, 06 Mar 2004 18:18:28 GMT, "Brett" <(E-Mail Removed)> wrote:

>Two areas where I've found 'goto' two be useful in other languages are in
>(untested examples in C++)
>
>(1) deeply nested loops
>
>for (k=0; k < 10; ++k)
>for (j=0; j < 10; ++j)
>for (i=0; i <10; ++i)
> if (/* some test */) goto END;
>
>END: /* continue */;
>
>and (2) repeating a while or for loop from the beginning:
>
>BEGIN:
>for (n=0; n < 20; ++n)
> if (/* some test */) goto BEGIN;
>
>What are the techniques in python for simulating these algorithms without a
>'goto' command?


I've been using C++ quite a while and never needed either of those
patterns. I have used a goto in C++ not too long ago, but not for
anything close to your examples, and its my first time in any language
for at least 10 years.

The reason for it was what I call a 'short running state machine' - a
state machine which needs to run to completion when invoked. I could
have used a loop with an embedded switch statement, but that just
didn't fit what was happening and would have made the code less
readable and maintainable - a goto is the natural representation of a
transition between states.

Once in ten years of doing a lot of programming. I don't think many
people need to worry about this use case

The normal reason for needing to exit deep loops (or any deep set of
structures), and a common reason for using goto in C, is due to an
error condition. In that case, throw an exception. This is a much
better way to handle errors as the code that throws the exception
doesn't need to know how (or if) the exception will be handled.

The only other common case where I've seen C's goto considered a good
thing is in search algorithms. The easy exit from the (probably
nested) loops can be useful. But when doing searches I tend to regard
success as the exceptional case and throw an exception for it, though
I don't think I've used the technique in Python to date.


If you have a use case for the loop restarting, I'd like to see it.
With a use case it is much easier to provide an alternative, and there
isn't any that strikes me as obvious as it stands.


--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
 
Reply With Quote
 
 
 
 
Roy Smith
Guest
Posts: n/a
 
      03-07-2004
Stephen Horne <(E-Mail Removed)> wrote:

> a goto is the natural representation of a transition between states.


Except that a goto allows the code for a state to be fallen into from
the top.

The best way I know to implement a state machine in Python is one
function for each state, and have each function return the next state,
or perhaps an (output, nextState) tuple. Your main loop then becomes
something like:

state = start
while state != end:
nextState, output = state (input)
print output
state = nextState

I would use a similar strategy in a language like C or C++ which allowed
you to pass function pointers around.

I've implemented state machines in Perl with a huge multi-way
if/elif/elif/else statement. It's pretty ugly, but it beats gotos.
 
Reply With Quote
 
 
 
 
Stephen Horne
Guest
Posts: n/a
 
      03-07-2004
On Sun, 07 Mar 2004 13:54:33 -0500, Roy Smith <(E-Mail Removed)> wrote:

>Stephen Horne <(E-Mail Removed)> wrote:
>
>> a goto is the natural representation of a transition between states.

>
>Except that a goto allows the code for a state to be fallen into from
>the top.


How is this different to the more typical switch-within-loop method?
Or have you never forgotten to include a 'break'?

>The best way I know to implement a state machine in Python is one
>function for each state, and have each function return the next state,
>or perhaps an (output, nextState) tuple. Your main loop then becomes
>something like:
>
> state = start
> while state != end:
> nextState, output = state (input)
> print output
> state = nextState


I've done similar in C++. In some extreme cases, I have used a class
heirarchy with a class for each state, using a virtual method to get
essentially the same effect. Having different members depending on the
state can be useful at times, though of course there is a price to
pay.

The same can of course be done in Python, and probably without all the
classes because of the dynamic nature of Python objects.

The point with my 'short running' example, though, is that it didn't
have input as such to worry about. Everything it needed to work on was
available at the time it was invoked. If it had needed to wait for
input sometimes I'd have needed a way to resume from a given state
anyway, implying the switch-for-the-state method or whatever.

Using functions or objects for the states would have meant making a
bunch of local variables accessible by those functions/objects, and
would have meant taking the states code out of context. Often this
would be a good thing, but not in this case - keeping the code in
context makes it much clearer.

The other consideration was that this was an inner loop in a function
that needed to run quickly. Adding function call overheads (especially
with lots of parameters) wasn't an option.

>I've implemented state machines in Perl with a huge multi-way
>if/elif/elif/else statement. It's pretty ugly, but it beats gotos.


If you say so. But in reality, but returning a function pointer to a
function that is immediately going to call that function pointer,
you're basically just faking the effect of a goto anyway.

Implementing a state machine using gotos (in those extremely rare
cases where it is an option) does not damage readability or
maintainability. Implementing a transition as 'return statefn;' or as
'statevar = stateid;' is really no different than implementing it as
'goto statelabel;'. All are a potential cause of spaghetti code if
abused, because all are just means of branching to a different piece
of code - its just that the goto does exactly what it says, while the
other methods achieve it indirectly. In fact its basically a special
case of the state variable method, using the processors IP as the
state variable.

That said, I did try to avoid using gotos anyway - using a goto is
basically begging to be harassed. I didn't use the loop-and-switch
method, but instead tried to pretent it wasn't really a state machine
by using a birdsnest of loops and conditionals. Never let anyone tell
you that structured code is inherently clean and simple - there's
always a special case where it all goes horribly wrong.

After three fatally buggy attempts using structured code, which I
realised I couldn't understand and thus couldn't debug, I gave up and
used gotos. The result worked first time, and other people have also
been able to understand it easily.


--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
 
Reply With Quote
 
Roy Smith
Guest
Posts: n/a
 
      03-07-2004
Stephen Horne <(E-Mail Removed)> wrote:
>> goto allows the code for a state to be fallen into from the top.

>
> How is this different to the more typical switch-within-loop method?


Not much. The C switch statement isn't much better than a goto, for
just that reason

> returning a function pointer to a
> function that is immediately going to call that function pointer,
> you're basically just faking the effect of a goto anyway.


In some respects, you're right. Certainly, both ways get you the same
pseudo-random flow of control, but that's inherent in a state machine.
What the function-per-state approach gets you is modularity. Each
function at least has its own namespace and set of local variables.

To tie this in with the current thread on unit testing, it's also a lot
easier to test a bunch of little functions than a collection of gotos.
You said:

> In fact its basically a special case of the state variable method,
> using the processors IP as the state variable.


That's a very good observation. Imagine you implemented your state
machine with gotos. To test each transition, you need to get the
machine into the right state before each test by feeding it a sequence
of inputs which navigates your state graph in the right way. That's
complicated and error prone to design (the last thing you want is an
error-prone test procedure). If there were many states and edges, it
would be very slow. If the state machine is non-deterministic (timing
dependencies, perhaps), it would be impossible.

Of course, this is all assuming that the logic implemented in each state
is different enough to require writing individual functions. Some state
machines (like those that execute compiled regular expressions) are
simple enough to be table driven. With a tabular approach, you get the
same testability you do with the functional approach; you can set the
machine to any random state, apply a single input, and see what happens.
You can't do that with gotos because the state is stored in a place
that's not exposed at the language level (unless you're writing in
assembler).
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
WTB: I BUY SOFTWARE - CHECK AROUND - YOU PROBABLY HAVE SOME OF THEBELOW LAYING AROUND. Network/Software Buyer C++ 0 05-23-2010 07:14 PM
getting around lack of bool type support ssylee C Programming 25 01-03-2008 07:08 AM
Microsoft & patents: what goes around comes around... Lawrence D'Oliveiro NZ Computing 104 12-16-2006 07:11 AM
Read all of this to understand how it works. then check around on otherRead all of this to understand how it works. then check around on other thelisa martin Computer Support 2 08-18-2005 06:40 AM
Make wxListCtrl fit around contents and parent frame fit around listctrl Piet Python 0 07-18-2004 08:27 AM



Advertisments