重新定义子例程时没有足够的参数

时间:2018-01-08 09:52:32

标签: perl arguments subroutine

当我重新定义我自己的子程序(而不是Perl内置函数)时,如下所示:

perl -ce 'sub a($$$){} sub b {a(@_)}'

我收到此错误:

  

没有足够的参数为main :: a at -e line 1,near" @_)"

我想知道为什么。

编辑:

"重新定义"可能没有很好的选择。但在我的情况下(我可能应该已经解释了我原本想要做的事情),我想重新定义(并且这里"重新定义"有意义)Test :: More ::是首先打印的功能测试结果前的日期和时间。

这就是我所做的:

Test::More.pm :

sub is ($$;$) {
    my $tb = Test::More->builder;

    return $tb->is_eq(@_);
}


MyModule.pm :

sub is ($$;$) {
   my $t    = gmtime(time);
   my $date = $t->ymd('/').' '.$t->hms.' ';

   print($date);
   Test::More::is(@_);
}

3 个答案:

答案 0 :(得分:7)

您为子程序提供的原型(从Test::More::is复制)表示您的子程序需要两个必需参数和一个可选参数。传入单个数组将无法满足该原型 - 它被视为将在标量上下文中进行评估的单个参数。

修复方法是检索传递给子例程的两个(或三个)参数,并将它们分别传递给Test::More::is

sub is ($$;$) {
   my ($got, $expected, $test_name) = @_;

   my $t    = gmtime(time);
   my $date = $t->ymd('/').' '.$t->hms.' ';

   print($date);
   Test::More::is($got, $expected, $test_name);
}

这个问题与你使用原型无关,或者你正在重新定义子程序这一事实(严格来说,你不是因为这两个子程序在不同的包中),但是它不是这样的。因为Test::More::is()有原型。

答案 1 :(得分:5)

你不是在这里重新定义任何东西。

您通过说a为您的子sub a($$$)设置了prototype。函数定义中的美元符号告诉Perl该子函数正好有三个标量参数。当你用a(@_)调用它时,Perl不知道该列表中有多少个元素,因此它不知道调用将有多少个参数,并且在编译时失败。

不要乱用原型。你可能不需要它们。

相反,如果你知道你的sub需要三个参数,请在你调用它的地方明确地抓住它们。

sub a($$$) {
    ...
} 

sub b {
    my ($one, $two, $three) = @_; 
    a($one, $two, $three);
}

或者更好的是,根本不要使用原型。

此外,ab是可怕的名字。不要使用它们。

答案 2 :(得分:4)

在Perl中,原型不会像修改解析规则那样验证参数。 $(document).on('click', '.className', function(){ //do stuff});表示子要求来电者与$$;$is(EXPR, EXPR)匹配。

在这种情况下,绕过原型是理想的。

is(EXPR, EXPR, EXPR)

由于您并不关心sub is($$;$) { print gmtime->strftime("%Y/%m/%d %H:%M:%S "); return &Test::More::is(@_); } 是否会修改您的Test::More::is,因此以下是一项简单的优化:

@_

如果sub is($$;$) { print gmtime->strftime("%Y/%m/%d %H:%M:%S "); return &Test::More::is; } 使用Test::More::is,您会发现以下内容非常有用:

caller