Hash subroutine and optional scalar argument

I have a routine with a prototype like this:

sub printFoo(%) { my (%hashFoo) =@ _; # do stuff with the hash } 

But I would like to additionally pass the second scalar argument as follows:

 sub printFoo(%;$) { my (%hashFoo,$optionalArg) =@ _; # do stuff with the hash and the optional arg } 

I understand that in warning mode this is no-no, but I'm not sure why.

I suppose I can use the global variable flag, but any advice on how to elegantly execute this type of function signature?

+5
source share
4 answers

I do not know if this is considered elegant, but ...

 sub printFoo { my $optionalArg; if (@_ % 2 != 0) { $optionalArg = pop @_; } my %hashFoo = @_; ... } 

A prototype with a hash link will also work. You will still call the function with a hash, but you must remember that the first hash argument will be received by your sub-mode as a hash reference.

 sub printFoo (\%;$) { # call as printFoo %foo or printFoo %foo, 42 my ($hashFooRef, $optionalArg) = @_; my %hashFoo = %$hashFooRef; ... } 
+4
source

Elegantly working with optional parameter:

 sub do_something { my (%params) = @_; my $debug = delete $params{debug} || 0; # do something with %params... } 
+2
source

If you use hash ref, as others suggested as the first argument, then checking the arguments after they are accepted is trivial:

 use strict; use warnings; my %hash = (a => 1, b => 2,); my $scalar = 1; printFoo(\%hash, $scalar); sub printFoo { my ($href, $opt) = @_; if(ref $href ne 'HASH' || $opt && ref \$opt ne 'SCALAR'){ die "Usage: printFoo(hashref, optional_scalar)\n"; } ... } 
+2
source

I agree with Hakon Hagland to use the hash link. To get more than one argument that you can choose, you need to pass in a few scalars, and not what is essentially a list, followed by something else.

I think this is not related to the question of whether to use prototypes or not. The warning system did you a favor by noting this, but I'm 99.44% sure that it will not work, even if you drop the prototype. You will still not have a value in your optional parameter.

+1
source

All Articles