Что означает объявление функции «sub function ($$)»? - PullRequest
6 голосов
/ 21 марта 2010

Я уже некоторое время использую Perl, но сегодня я наткнулся на этот код:

sub function1($$)
{
   //snip
}

Что это значит в Perl?

Ответы [ 2 ]

16 голосов
/ 21 марта 2010

Это функция с прототипом , которая принимает два скалярных аргумента.


Существуют веские аргументы, чтобы вообще не использовать прототипы Perl - как отмечено в комментариях ниже. Вероятно, самый сильный аргумент:

В 2008 году обсуждается StackOverflow:

Возможна замена в модуле MooseX :: Method :: Signatures .

11 голосов
/ 21 марта 2010

Как уже упоминалось в другом ответе, $$ объявляет прототип. Другой ответ не говорит о том, для чего нужны прототипы. Они не для проверки ввода, они являются подсказками для синтаксического анализатора.

Представьте, что у вас есть две функции, объявленные как:

sub foo($)  { ... }
sub bar($$) { ... }

Теперь, когда вы пишете что-то неоднозначное, например:

foo bar 1, 2

Перл знает, где положить паренс; Бар занимает два аргумента, поэтому он потребляет два ближайших к нему. foo принимает один аргумент, поэтому он берет результат bar и два аргумента:

foo(bar(1,2))

Другой пример:

bar foo 2, 3

То же самое относится; foo берет один аргумент, поэтому он получает 2. столбец принимает два аргумента, поэтому он получает foo(2) и 3:

bar(foo(2),3)

Это довольно важная часть Perl, поэтому игнорирование ее как «никогда не использовать» приносит вам медвежью услугу. Почти каждая внутренняя функция использует прототипы, поэтому, понимая, как они работают в вашем собственном коде, вы можете лучше понять, как они используются встроенными функциями. Тогда вы можете избежать ненужных скобок, что делает код более приятным.

Наконец, один анти-шаблон, против которого я вас предупрежу:

package Class;
sub new ($$) { bless $_[1] }
sub method ($) { $_[0]->{whatever} }

Когда вы вызываете код как методы (Class->method или $instance->method), проверка прототипа совершенно бессмысленна. Если ваш код может быть вызван только как метод, добавление прототипа является неправильным. Я видел некоторые популярные модули, которые делают это (привет, XML::Compile), но это неправильно, поэтому не делайте этого. Если вы хотите задокументировать, сколько аргументов нужно передать, как насчет:

sub foo {
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify
    ....

или

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....

В отличие от foo($$), они значимы и читабельны.

...