带有散列和可选标量参数的子例程

时间:2015-09-04 13:40:45

标签: perl

我有一个子程序,原型如下:

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

但我希望可以选择传递第二个标量参数:

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

据我所知,在警告模式下,这是禁忌,但我不确定原因。

我想我可以使用全局变量标志,但有关如何优雅地完成此类函数签名的任何建议吗?

4 个答案:

答案 0 :(得分:4)

我不知道这是否算得很优雅,但......

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

带有哈希引用的原型也可以。您仍然会使用散列调用该函数,但您必须记住您的sub将接收的第一个散列arg作为散列引用。

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

答案 1 :(得分:2)

优雅地处理可选参数:

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

答案 2 :(得分:2)

如果您使用散列引用,因为其他人建议将其作为第一个arg,那么在接受它们之后检查args是微不足道的:

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";
    }

    ...
}

答案 3 :(得分:1)

我同意Hakon Haegland关于使用散列引用的看法。为了得到你可以选择的多个参数,你需要传递多个标量,而不是基本上是一个列表,后跟其他东西。

我认为这与你是否应该使用原型的问题无关。通过标记这个警告系统帮了你一个忙,但我99.44%肯定即使你丢弃原型它也行不通。您仍然不会在可选参数中得到一个值。