Perlcritic - 子程序原型

En-*_*ion 0 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);
}
Run Code Online (Sandbox Code Playgroud)

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

这样可以,或者我应该考虑不同的解决方案?

Kei*_*son 19

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

sub func($@) {
    # ...
}
Run Code Online (Sandbox Code Playgroud)

对此:

func($@) {
    # ...
}
Run Code Online (Sandbox Code Playgroud)

perlcritic停止抱怨原型 - 但我认为这只是一个关于perlcritic的故障.没有sub关键字,那就不再是子程序定义了; 这是一个语法错误,因为你会看到你是否尝试运行它或检查它perl -cw.检查您的代码是否有效Perl并不是真正的perlcritic工作; 它显然假定它是,然后警告你关于风格问题.如果你输入无效的Perl,所有的赌注都会被取消.

如今,人们普遍认为使用Perl原型通常不是一个好主意.

Perlcritic基于Damian Conway的"Perl Best Practices"一书.从第194页开始的部分标题为"不要使用子程序原型".

这本书不公开,所以我不能引用或链接到这里的部分,但是chromatic有一篇博客文章 "原型问题",其中包括:

原型的主要问题是它们的行为与大多数人第一次遇到它们时的预期不同.原型可以改变后续代码的解析,并且可以强制参数的类型.它们不作为子例程所期望的参数的数量或类型的文档,也不将参数映射到命名参数.

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

另见perldoc perlsub:

当然,这一切都非常强大,应该只在适度的情况下使用才能让世界变得更美好.


Ala*_*avi 17

正如消息所示,您已经使用了子例程原型.你很可能不需要它们.

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

sub foo()
Run Code Online (Sandbox Code Playgroud)

将其更改为:

sub foo
Run Code Online (Sandbox Code Playgroud)

请注意删除()之间的任何内容.


use*_*419 9

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

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

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

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

所以打电话就好

fun1(@args)  
Run Code Online (Sandbox Code Playgroud)

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

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

    sub fun2($$ \%){}

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
Run Code Online (Sandbox Code Playgroud)


bra*_*buz 6

较新的 Perls 有一个签名功能,虽然仍被标记为实验性的,但很受欢迎,被这条规则标记了。签名是在这篇原始帖子之后引入的,可能是 En-Motion 想要的。

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

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

将以下内容添加到 ~/.perlcriticrc

[-Subroutines::ProhibitSubroutinePrototypes]

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

考虑:

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

带签名:

使用特征“签名”;

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