不鼓励的perl习语的起源:&x(...)和sub x($$){...}

kno*_*orv 4 perl coding-style

在我的perl代码中,我之前使用过以下两种写作风格,我后来发现它们在现代perl中被劝阻:

# Style #1: Using & before calling a user-defined subroutine
&name_of_subroutine($something, $something_else);

# Style #2: Using ($$) to show the number of arguments in a user-defined sub
sub name_of_subroutine($$) {
  # the body of a subroutine taking two arguments.
}
Run Code Online (Sandbox Code Playgroud)

由于不了解这些风格,我只是停止使用它们.

但是,出于好奇,我想知道以下内容:

  • 这两种写作风格的起源是什么?(我敢肯定我自己没有想过这些款式.)
  • 为什么这两种写作风格在现代的perl中黯然失色?
  • 这些风格在某个时间点被认为是最佳实践吗?

Eri*_*rom 15

由于&两个原因,sigil通常不用于现代Perl中的函数调用.首先,它很大程度上是多余的,因为Perl会将任何看起来像函数(后跟parens)的东西视为一个函数.其次,方式&function()&function执行之间存在重大差异,这可能会让经验不足的Perl程序员感到困惑.在第一种情况下,调用该函数时不带参数.在第二种情况下,使用当前函数调用函数@_(它甚至可以对参数列表进行更改,这将在该范围内的后续语句中看到:

sub print_and_remove_first_arg {print 'first arg: ', shift, "\n"}

sub test {
   &print_and_remove_first_arg;

   print "remaining args: @_\n";
}

test 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)

版画

first arg: 1
remaining args: 2 3
Run Code Online (Sandbox Code Playgroud)

所以最终,使用&每个函数调用最终隐藏了几个&function;调用,这些调用可能导致很难找到错误.此外,使用&sigil可以防止功能原型的使用,这在某些情况下很有用(如果你知道你在做什么),但也可能导致难以追踪错误.最终,它&是功能行为的强大修饰符,只应在需要该行为时使用.

原型是相似的,它们的使用应该在现代Perl中受到限制.必须明确说明的是Perl中的原型不是函数签名.它们是编译器的提示,告诉它以与内置函数类似的方式解析对这些函数的调用.也就是说,原型中的每个符号都告诉编译器在参数上强加那种类型的上下文.定义行为类似的功能时,此功能是非常有帮助mappush或者keys其所有不同的对待自己的第一个参数比标准清单将运营商.

sub my_map (&@) {...}  # first arg is either a block or explicit code reference

my @ret = my_map {some_function($_)} 1 .. 10;
Run Code Online (Sandbox Code Playgroud)

原因的原因sub ($$) {...}和类似用途是不鼓励的,因为作者中有9次意味着"我想要两个参数"而不是"我想要两个参数,每个参数都有一个强加于呼叫网站的标量上下文".前一个断言写得更好:

use Carp;
sub needs2 {
   @_ == 2 or croak 'needs2 takes 2 arguments';
   ...
}
Run Code Online (Sandbox Code Playgroud)

这将允许以下调用样式按预期工作:

my @array = (2, 4);

needs2 @array;
Run Code Online (Sandbox Code Playgroud)

总而言之,&sigil和函数原型都是有用且功能强大的工具,但只有在需要该功能时才能使用它们.它们的多余使用(或作为参数验证的误用)导致意外行为并且难以追踪错误.