Preceptor has asked for the wisdom of the Perl Monks concerning the following question:

On a number of occasions, now, I've had a need, (well not so much a need as a desire), to implement a 'command handler'.
The concept being that I run myperl.pl update which would call the appropriate subroutine to do an update.
The way in which I've been doing this, is something like:
my %command_list = ( 'update' => { args => 2, function => *refresh_list, }, ); my $input=$ARGV[0] &{ $command_list{$input}{'function'} }
(The actual sub, and the validation is missing for simplicity).
I suppose my question is, is there a better way of doing this?
(And a secondary question, if you look at the code I hacked together in emud.pl, even when I insert 'use strict' it allows me to use strings as sub refs, but in more recent code, it doesn't. This is somewhat confusing)
--
It's not pessimism if there is a worse option, it's not paranoia when they are and it's not cynicism when you're right.

Replies are listed 'Best First'.
Re: Best way to handle 'commands'
by blakem (Monsignor) on Sep 19, 2002 at 11:18 UTC
    What you have there is commonly called a dispatch table. Searching for 'dispatch table' gives quite a few good nodes about the subject.

    -Blake

      Ah marvellous. That's almost exactly what I was looking for.
      Of course, most of the examples seem to use \&subroutine wheras I've been getting away with *subroutine. I'd imagine they are different, but can anyone enlighten me as to how? (and if what I'm doing is an example of wrongness, or just differentness...)
      Update:After reading perlref, I get some of the idea.
      --
      It's not pessimism if there is a worse option, it's not paranoia when they are and it's not cynicism when you're right.
        *subroutine is actually a typeglob. Typeglobs harken back to the days of Perl 4, before references were around. In most normal situations you shouldn't need to use them now that we have real refs.

        What you've actually done is create an alias that refers to all "things" named 'refresh_list' That includes &refresh_list, $refresh_list, %refresh_list, @refresh_list, and a few more esoteric items.

        #!/usr/bin/perl -w use strict; use vars qw($refresh_list %refresh_list @refresh_list); %refresh_list = @refresh_list = 1..10; $refresh_list = 'Im a scalar'; sub refresh_list { return "Im a subroutine" }; my %command_list = ( 'update' => { args => 2, function => *refresh_list, }, ); print "Sub: " . &{ $command_list{update}{'function'} } . "\n"; print "Scalar: " . ${ $command_list{update}{'function'} } . "\n"; print "Hash: " . %{ $command_list{update}{'function'} } . "\n"; print "Array: " . @{ $command_list{update}{'function'} } . "\n"; __END__ Sub: Im a subroutine Scalar: Im a scalar Hash: 4/8 Array: 10

        -Blake

Re: Best way to handle 'commands'
by fglock (Vicar) on Sep 19, 2002 at 13:04 UTC

    Best way is to use Getopt::Long !

    update: FoxtrotUniform has a point here. Getopt forces you to accept some conventions. Using Getopt is actually a matter of taste.

      Why? It's not as if the OP has a lot of options handling to do. For one thing, (for example) apachectl restart is just as nice as (if not nicer than) apachectl --restart, and from the programmer's perspective:

      for my $cmd (@ARGV) { &{$dispatch->{$cmd}} or warn "Unrecognized command $cmd!\n"; }

      is about as good as:

      for my $cmd (keys %$opts) { &{$dispatch->{$cmd}} or warn "Unrecognized command $cmd!\n"; }

      In this context, what advantages do the Getopt modules have?

      --
      F o x t r o t U n i f o r m
      Found a typo in this node? /msg me
      The hell with paco, vote for Erudil!