【问题标题】:How to pass optional arguments to a function如何将可选参数传递给函数
【发布时间】:2014-12-16 15:12:24
【问题描述】:

我正在尝试使模块的函数接受以下形式的可选参数:

function(arg1, optional1 => opt1, optional2 => opt2, ..);

但我找不到任何地方可以很好地解释如何做到这一点。我想出了以下解决方案来接受 email、alpha 和 html 参数,但它非常复杂,我不敢相信没有更短的方法可以实现这一点:

sub test
{
    my ($s, @args) = @_;
    my $alpha = 1;
    my $html = 0;
    my $email = 0;
    for(my $i = 0; $i < scalar(@args); $i++)
    {
        if($args[$i] eq "alpha")
        {
            $i++;
            $alpha = $args[$i];
        }
        elsif($args[$i] eq "email")
        {
            $i++;
            $email = $args[$i];
        }
        elsif($args[$i] eq "html")
        {
            $i++;
            $html = $args[$i];
        }
    }
    return ($alpha, $email, $html);
}

my ($a, $b, $c) = test("stuff", ndhgffs => 1, email => 1, alpha => 0);

print $a . $b . $c;

编辑:

感谢下面的答案和下面的cmets,这解决了它:

sub test
{
   my ($s, %opts) = @_;
   my $email = $opts{'email'} // 0;
   my $alpha = $opts{'alpha'} // 1;
   my $html = $opts{'html'} // 0;
   return ($alpha, $email, $html);
}

【问题讨论】:

  • 另一种方法是传递哈希引用。
  • alpha 是布尔值吗?如果是这样,$opts{'alpha'} // 1 很容易出错。考虑$opts{'no_alpha'} // 0(或只是$opts{'no_alpha'})。
  • OT 但是如何使用函数签名来处理这个问题?可以发布 5.20 use experimental 'signatures' 为这类事情提供更干净的“成语”吗?当您有复杂的函数参数时,从@_ 抓取东西似乎非常整洁/干净并且可以自我记录...... TIMTOWTDI && ♥ perl :-)
  • 在这个例子中是的,函数将是布尔值,尽管我认为// 也应该与字符串一起使用..

标签: perl function subroutine


【解决方案1】:
sub function {
   my $arg1 = shift;
   my $arg2 = shift;
   my %opts = @_;
   my $optional1 = delete($opts{$optional1});
   my $optional2 = delete($opts{$optional2});
   croak("Unrecognized parameters ".join(' ', keys(%opts))) if %opts;
   ...
}

或

sub function {
   my ($arg1, $arg2, %opts) = @_;
   my $optional1 = delete($opts{$optional1});
   my $optional2 = delete($opts{$optional2});
   croak("Unrecognized parameters ".join(' ', keys(%opts))) if %opts;
   ...
}

注意事项:

  • 如果您不想检查无法识别的选项,则不需要delete。

  • 当参数被省略或取消定义时,您可以轻松地分配默认值

    my $arg = delete($opts{$arg}) // 'default';   # Perl 5.10+
    

【讨论】:

  • 在这种情况下应该使用delete吗?
  • 习惯。它允许die "Unrecognized args" if %opts;。如果您不使用该检查,则不需要delete。
  • 不应该编辑你的评论,你原来的评论很好,我不知道'//'。
  • @Dendory 我很确定 // 是一个帖子 5.10 的东西 - IOW 这是一个新的现代 perl 功能,从千禧年早期开始(这是否使它在 Perl 方面成熟?)。如果您维护在不可触碰的5.8.* 安装上运行的关键业务应用程序,那么您不会知道这很正常……实际上您可能应该尝试忘记 ;-)
  • @G. Cito,仍在使用 5.8 的人不会修补它以添加 //。 (实际上确实存在补丁。)
【解决方案2】:

如果子例程参数是从@_ 的值复制并分配给函数“按出现顺序”的变量,那么您的函数可以编写为具有您可以使用defined OR operator // 设置的默认值,或者,如果这些值确实是可选的并且并不总是需要,那么您可以分配一个占位符值(例如not_set),然后在函数从@_ 读取其参数后删除/删除它喜欢:

for (keys %opthash){ if ($opthash{$_} =~ /not_set/)  {delete $opthash{$_} }}

如果此功能被大量使用,我不确定这是最有效的方法。

【讨论】:

    猜你喜欢
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 2018-11-03
    • 2019-03-17
    相关资源
    最近更新 更多