goto considered essential
Consider the following program fragment, which copies one text file into
another text file:
sequence cmd_args
sequence cmd_line_words
sequence input_file_name
integer input_file_nr
object line
sequence output_file_name
integer output_file_nr
cmd_line_words = command_line ( )
if length ( cmd_line_words ) != 4 then
Printf ( "Exactly two arguments expected -- %d supplied.\n",
{ length ( cmd_line_words ) - 2 } )
else
cmd_args = cmd_line_words [ 3..4 ]
input_file_name = cmd_args [ 1 ]
input_file_nr = open ( input_file_name, "r" )
if input_file_nr = -1 then
Printf ( "Can't open input file %s.\n",
{ input_file_name } )
else
output_file_name = cmd_args [ 2 ]
output_file_nr = open ( output_file_name, "w" )
if output_file_nr = -1 then
Printf ( "Can't open output file %s.\n",
{ output_file_name } )
else
while 1 do
line = gets ( input_file_nr )
if atom ( line ) then
exit
end if
puts ( output_file_nr, line )
end while
Printf ( "%s copied to %s.\n",
{ input_file_name, output_file_name } )
end if
end if
end if
Without a goto statement, or something like it, we have the creeping margin
problem. In production code, with many error checks in the main logic, this
can make code very hard to understand. With a goto, we have
cmd_line_words = command_line ( )
if length ( cmd_line_words ) != 4 then
goto arg_count_is_wrong
end if
cmd_args = cmd_line_words [ 3..4 ]
input_file_name = cmd_args [ 1 ]
input_file_nr = open ( input_file_name, "r" )
if input_file_nr = -1 then
goto cant_open_input_file
end if
output_file_name = cmd_args [ 2 ]
output_file_nr = open ( output_file_name, "w" )
if output_file_nr = -1 then
goto cant_open_output_file
end if
while 1 do
line = gets ( input_file_nr )
if atom ( line ) then
exit
end if
puts ( output_file_nr, line )
end while
Printf ( "%s copied to %s.\n",
{ input_file_name, output_file_name } )
goto halt
arg_count_is_wrong:
Printf ( "Exactly two arguments expected -- %d supplied.\n",
{ length ( cmd_line_words ) - 2 } )
goto halt
cant_open_input_file:
Printf ( "Can't open input file %s.\n", { input_file_name } )
goto halt
cant_open_output_file:
Printf ( "Can't open output file %s.\n", { output_file_name } )
goto halt
halt:
Here, the main (non-error) logic is much more apparent. But what, you ask,
is then to prevent evil programmers from generating spaghetti code? Well,
nothing. So perhaps a more constrained construct would be better. In the
spirit of Ada exceptions, we might try something like this:
--
-- Function/procedure body or main program starts here.
--
cmd_line_words = command_line ( )
exception arg_count_is_wrong if length ( cmd_line_words ) != 4
cmd_args = cmd_line_words [ 3..4 ]
input_file_name = cmd_args [ 1 ]
input_file_nr = open ( input_file_name, "r" )
exception cant_open_input_file if input_file_nr = -1
output_file_name = cmd_args [ 2 ]
output_file_nr = open ( output_file_name, "w" )
exception cant_open_output_file if output_file_nr = -1
while 1 do
line = gets ( input_file_nr )
exit if atom ( line )
puts ( output_file_nr, line )
end while
Printf ( "%s has been copied to %s.\n",
{ input_file_name, output_file_name } )
--
-- Normal function/procedure return or program termination occurs here.
-- Exception handlers follow function/procedure body or main program.
--
when arg_count_is_wrong do
Printf ( "Exactly two arguments expected -- %d supplied.\n",
{ length ( cmd_line_words ) - 2 } )
-- implicit return or halt here
when cant_open_input_file do
Printf ( "Can't open input file %s.\n", { input_file_name } )
-- implicit return or halt here
when cant_open_output_file do
Printf ( "Can't open output file %s.\n", { output_file_name } )
-- implicit return or halt here
--
-- Function/procedure body or main program source code ends here.
--
The main logic is really obvious here. Not only have we eliminated the
unconstrained goto, but we have reduced the number of lines per exception
check from three to one, thus reducing the visual noise that these checks
introduce into the main logic. (Also, note the Ada-like conditional exit
statement.)
For me, some such capability is necessary in any programming language that
is to be used to write large production-quality programs. I make these
points because I understand that a major new release of Euphoria might be
in the works, and so this might be a good time to consider new features.
What do you think?
Tom Dailey
|
Not Categorized, Please Help
|
|