goto statement considered
Everyone knows not to use goto, right? Dijkstra’s words on the subject have risen to the level of gospel in the programming community. Not that I do not completely agree… in most cases.
I have to admit that I occasionally resort to goto myself. This week was one such an occasion. But before you pick up your torch and farming implement of choice and join the mob heading for my castle gates, please consider that Dijkstra’s letter was complaining about unrestricted goto, which was a popular feature of languages at the time. It was an unstructured precursor of the subroutine and structured programming, which put goto on a leash and taught it not to bark at the neighbors. In restricting goto to local jumps, as most modern languages supporting the feature do, the beast became much less fearsome. In fact, a while loop is just a structured goto, as is try/catch (albeit with a little extra magic.)
Perl, of course, does not impose such restrictions on a programmer (although it does prohibit jumping into blocks that require initialization, such as other functions.) With a little discipline, though, goto is a feature and quite useful. It can be used to make extremely complex loops explicit and easy to follow as well as allow a loop to break to any outer loop in the current call stack.
As an example, I recently wrote a function to increment a string of arbitrary alphanumeric characters, where letters must maintain their case but increment as base-26 numbers and numbers increment normally (base 10). For example, if a letter increments past z, it becomes a and the next character to the left is then incremented. The increment logic fit into a function that took two of these strings and calculated all possible values in between to support some limited set operations against two alphanumeric ranges.
My original code for the increment logic was grisly at best. It took a series of nested while loops and state variables that were incremented or decremented as needed. I avoided recursion because the sequences were of arbitrary length. Breaking the code into subroutines made it more complex to maintain loop state. Using goto allowed me to break apart the logic into blocks without the overhead or state-passing necessary to shoehorn the logic into subroutines. I was able to label each part clearly and jump between them as needed to increment or “carry the 1.” I reduced the size of the code to just a couple dozen lines, including safety checks, and found that the goto code was much easier to read and reason about.
That said, I want to emphasize strongly that goto should be kept local. Jumping to outer function calls makes the logic of a program difficult to reason about and changes scope in confusing ways. But as a way of structuring complex loops and iterative logic, you just can’t beat goto.
Agreed! GOTO rocks. If constrained.
My usual heurisitics for gotos in C/C++ – no more then 1-3 labels and forward non-crossing jumps only.
Right. I have recently finished implementation of coroutines in Java ( – if you care), and I must admit that I would not have gone anywhere without goto (although bytecode one). That’s at the heart of resuming a coroutine execution. I started to think that goto has its place where it cannot be abused. But I also agree that it must be constrained so that careless programmers do not see it very often :-)
Setting aside the main point of your post –you mention Perl, so is it reasonable to assume that you were coding in Perl? If so, note that the
++
operator already behaves this way—see http://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement—and .. ranges behave as you’d hope.The number of columns in the string may not change and the increment operator would add a character to the beginning of the string. Also, the range operator does not appear to do what I need it to. I initially used that, but it cannot handle punctuation, which this must handle.
This post obviously lacks code examples. Show us.
Surely, you’ve seen Knuth’s take on the issue: Structured Programming with Goto. It’s very insightful reading on this topic, has some great humor, and presages a lot of great ideas seen in later development.
Post your code!
rather let the functional programming paradigm of programming structure your goto statement
If I understand your problem correctly, doesn’t this easily solve it without a goto statement:
def increment(string, by):
bytes = deque()
for c in string:
byte = ord(c)
if ord(“0″) <= byte <= ord("9"):
byte -= ord("0")
byte = (byte + by) % 9
byte += ord("0")
elif ord("a") <= byte <= ord("z"):
byte -= ord("a")
byte = (byte + by) % 25
byte += ord("a")
elif ord("A") <= byte <= ord("Z"):
byte -= ord("A")
byte = (byte + by) % 25
byte += ord("A")
bytes.append(byte)
return "".join(bytes)
Yes, it's in Python, but easily convertible to Perl and you can extract the inner part of the for loop into a function since you want to transform it char by char.