Perlcritic - 子程序原型

时间:2011-12-20 09:41:26

标签: perl

运行Perlcritic时出现此错误:

  

xx行x列使用的子程序原型。参见PBP第194页。   (严重程度:5)

子程序是:

sub zFormatDate() {
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = shift;
  return sprintf("%04d%02d%02d%02d%02d%02d",
    $year + 1900, $mon+1, $mday, $hour, $min, $sec);
}

如果我从我的函数中删除关键字'sub',它就会消失。

这样可以,还是应该查看不同的解决方案?

5 个答案:

答案 0 :(得分:18)

不,删除sub关键字肯定是解决方案。如果你改变了这个:

sub func($@) {
    # ...
}

到此:

func($@) {
    # ...
}

perlcritic停止抱怨原型 - 但我认为这只是一个小问题的故障。没有sub关键字,那不再是子例程定义;这是一个语法错误,因为您会看到是否尝试运行它或使用perl -cw进行检查。检查您的代码是否有效Perl并不是真正的perlcritic工作;它显然假定它是,然后警告你关于风格问题。如果您将其无效Perl,则所有投注均已关闭。

现在人们普遍认为使用Perl原型通常不是一个好主意。

Perlcritic基于达米安康威的书"Perl Best Practices"。从第194页开始的部分标题为“不要使用子程序原型”。

这本书不公开,所以我不能引用或链接到这里的部分,但是chromatic有blog entry“原型问题”,其中包括:

  

原型的主要问题是它们的行为不同于   大多数人在第一次遇到它们时都会期待。原型可以改变   后续代码的解析,他们可以强制类型   参数。它们不作为数量或类型的文档   arguments子例程期望,也不将参数映射到named   参数。

很容易假设Perl的原型类似于C的原型,它声明了函数所期望的参数的数量和类型(以及可选的名称)。事实上,他们是完全不同的。它们的主要目的是编写模仿内置函数行为的Perl子例程,例如不将数组展平为列表。

另见perldoc perlsub

  

当然,这一切都非常强大,只能用于   适度使世界变得更美好。

答案 1 :(得分:16)

如消息所示,您使用了subroutine prototypes。你很可能不需要它们。

目前您的子程序定义可能类似于:

sub foo()

将其更改为:

sub foo

请注意删除()以及介于两者之间的任何内容。

答案 2 :(得分:8)

Perl :: Critic认为子程序原型很糟糕。它不是关于“sub”关键字而是函数参数定义。删除“sub”将欺骗Perl :: Critic不报告错误但是你的代码无论如何都不会运行

您可能希望在以下两种情况之一中使用子程序原型:

  1. 你想用函数参数执行一些“魔法”,例如:

    sub fun1(\ @){ 我的($ ar_ref)= @_ }

  2. 所以像

    这样的电话
    fun1(@args)  
    

    不会将@args压入@_但会将@args作为数组引用传递给@_ [0]

    1. 您想清楚地说明功能签名

      sub fun2($$ \%){}

    2. fun2 args是标量,另一个标量和散列引用

      Perl最佳实践手册为这两种情况提供了使用场景,您可以轻松地使用自己的代码。 PBP给出的修正是:不要使用原型。

      如果您仍想使用它们,您可以告诉Perl :: Critic不要报告原型的使用情况:

      ## no critic
      # Perl::Critic will ignore any problems it sees with your code
      sub func_With_prototypes ($$$)
      {
      return undef
      }
      ## use critic
      # Perl::Critic will report any problems it sees within your code
      

答案 3 :(得分:2)

较新的Perls具有签名功能,尽管该功能仍被标记为实验性功能,但该规则所标记的功能非常受欢迎。签名是在此原始帖子之后介绍的,可能是En-Motion想要的。

因为Catalyst广泛使用了原型,所以不能弃用原型。 Catalyst破解了原型以提供动态路由系统。

如果使用签名功能(或Catalyst),最好的解决方案是通过〜/ .perlcriticrc禁用规则。

在〜/ .perlcriticrc中添加以下内容

  

[-Subroutines :: ProhibitSubroutinePrototypes]

虽然签名看起来像PerlCritic的原型,但它们却是Modern Perl编程的基本要素。

考虑:

  

sub add2nums {my $ num1 = shift;我的$ num2 =移位;返回$ num1 +   $ num2; }

签名:

  

使用功能“签名”;

     

sub add2nums($ num1,$ num2){返回$ num1 + $ num2; }

答案 4 :(得分:0)

我猜

sub zFormatDate() {
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = shift;
  return sprintf("%04d%02d%02d%02d%02d%02d",
    $year + 1900, $mon+1, $mday, $hour, $min, $sec);
}

打算阅读

sub zFormatDate($$$$$$$$$) {
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @_;
  return sprintf("%04d%02d%02d%02d%02d%02d",
    $year + 1900, $mon+1, $mday, $hour, $min, $sec);
}

也就是说,提供9个参数的原型,并正确设置my变量。