My Favorite Warnings: exiting
Perl has various ways to transfer control out of the normal flow: die()
, goto()
, return()
, next
, last
, and redo
are among the sorts of things I mean. Not all of these are suitable for all circumstances, and Perl issues an exiting
warning for unsuitable cases.
Sometimes, though, you just need to do something unsuitable. When I write an interactive script, it generally dispatches to a subroutine named after the function, something like so:
while ( defined( my $line = $term->readline( 'prompt> ' ) ) ) { my ( $cmd, @arg ) = shellwords( $line ); if ( my $code = __PACKAGE__->can( "cmd_$cmd" ) ) { $code->( @arg ); } else { warn "Unknown command $cmd\n"; } }
I find this very handy; if I want to add a command, all I have to do is write a subroutine. But when I write sub cmd_exit{ ... }
, it is not clear what goes inside the subroutine. The "proper" implementation is probably to have cmd_exit()
, and only that subroutine, return a code that means it's time to exit the loop, and then test the return code and act appropriately. Suddenly the code got a little more complicated.
When refactoring a chained if ( ... ) { ... } elsif ( ... ) ...
implementation into subroutines, I stumbled across the fact that you can, in fact, exit a subroutine with last
. Perl warns about it, because it is not at all the usual way to do things. But it will work, and the implementation of the exit
command becomes
sub cmd_exit { no warnings qw{ exiting }; last; }
The cautious programmer may wish to label the main loop and specify that label in the last
statement.
Notes relevant to the code samples, but irrelevant to the warning being discussed:
- The script samples assume
$term
is aTerm::ReadLine
object, and thatshellwords()
comes fromText::ParseWords
. - A more useful example of the above dispatch loop will guard against empty lines (
$cmd
isundef
) and comments, however defined. - The dispatch loop might also want to execute
$code->( @arg )
inside aneval { ... }
. - The problem with
sub cmd_exit { exit }
is that any cleanup after the dispatch loop does not get done. Time for "My Favorite Scheduled Blocks?"
Previous entries in this series:
I do not trigger it ever, even do not know it exists, thank you :)
This series has been interesting. Thanks for that.
Plus, TIL about `Text::ParseWords`. Double thanks!