SPUG: argument-less shift - explicit/implicit [was: Hashes and subroutines]

Michael R. Wolf MichaelRWolf at att.net
Thu Jan 8 11:16:18 PST 2009

On Jan 7, 2009, at 8:55 PM, Jack Foy wrote:

> Michael R. Wolf wrote:
>> Jack Foy wrote:
>>> sub runCommand {
>>> 	my $command = shift;
>>> 	my $rArgs = shift;	# or use @_, but see note 1
>> This seems backwards to my way of thinking (i.e. my way of reading  
>> and
>> writing code for my own and other's use):
>>    You use @_ *implicitly*, but state that *explicit* code is easier
>> to read.
> You're right, I was unclear.  I meant, it's more explicit to call our
> hypothetical routine like so:
> 	runCommand ($command, \@commandArgs);
> rather than something like this:
> 	runCommand ($command, @commandArgs);
> You gave one example of how that might be implemented:
>> sub xxx {
>>    my ($first_arg, $second_arg, @remaining_args) = @_;
>> }
> I avoid that approach because it makes it much more expensive to pass
> around and manipulate large data structures (by requiring a copy of
> every element of @remaining_args).

OK.  Got it.  I agree.  SImple arguments should come in as a list, but  
complex or large arguments should come in as a reference.

In that case, I typically tack "_ref" to the end of the variable.  I  
typically do *not* like hungarian notation, but since scalars can be  
used for so many things, it's more readable (for my definition of  
readable) to differentiate the different kinds of scalars.  I guess  
what I'd call $action_ref, you call $rAction.  Since my fingers grew  
up at Bell Labs (writing C), I tend to use underscore more than the  
shift key.

I still don't like shift without an argument.  It's too contextual for  
my taste.

> By the way, note that a further alternative is to use the "magic  
> goto":
> sub runCommand {
>        my $command = shift;

Thanks for *showing* the magic...

>        goto &$rAction;
> }
> This really does behave as though the caller to runCommand() actually
> invoked the selected caller directly!  It replaces runCommand() with  
> the
> selected routine on the call stack, with @_ as the argument.  There  
> are
> rare times when this is the Right Thing.  Use with appropriate  
> caution.

... and thanks for warning about its limited usefulness.

Since it's such powerful "magic", I'd be tempted to put in a comment.

Factoring in your suggestions, I'd refactor the code to

sub runCommand {
        my $command = shift @_;

        my %actions = (
                play    => \&sub1,
                that    => \&sub2,
                funky   => \&sub3,
                music   => \&sub4,
                'white boy' => sub { 'lay down the rhythm and play  
that funky music' until 'you die' }

        my $action_ref = $actions{$command};

        # Magic goto...
        goto &{$action_ref} if $action_ref;
        return LogError ("Unknown command '$command'");

Depending on the level of *other* readers, I may or may not augment  
the "magic goto" comment.

Michael R. Wolf
     All mammals learn by playing!
         MichaelRWolf at att.net

More information about the spug-list mailing list