шпаргалка Когда следует использовать & для вызова подпрограммы Perl?




регулярные выражения. 3-е изд. (4)

Я прочитал аргументы против использования '&', но я почти всегда использую его. Это экономит мне слишком много времени, чтобы не делать этого. Я трачу очень большую часть своего времени кодирования в Perl и ищу, какие части кода вызывают определенную функцию. С ведущим &, я могу искать и находить их мгновенно. Без ведущего & я получаю инструкции определения функций, комментариев и отладки, обычно увеличивая количество кода, который я должен проверить, чтобы найти то, что я ищу.

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

Я слышал, что люди не должны использовать & для вызова подложек Perl, то есть:

function($a,$b,...);
# opposed to
&function($a,$b,...);

Я знаю, что для одного список аргументов становится необязательным, но что такое случаи, когда целесообразно использовать & и случаи, когда вы абсолютно не должны его использовать?

Также как здесь происходит увеличение производительности, когда вы упускаете & ?


Форма & subproutine () отключает проверку прототипов. Это может быть или не быть тем, что вы хотите.

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

Прототипы позволяют указывать числа и типы аргументов подпрограммы и проверять их во время компиляции. Это может обеспечить полезную диагностическую помощь.

Прототипы не применяются к вызовам методов или вызовам, выполненным в старомодном стиле, с использованием префикса &.

& & Необходимо для ссылки или разыменования подпрограммы или ссылки на код

например

sub foo {
   # a subroutine
}

my $subref = \&foo; # take a reference to the subroutine

&$subref(@args);  # make a subroutine call using the reference.

my $anon_func = sub { ... }; # anonymous code reference
&$anon_func(); # called like this

Протипы также не применимы к ссылкам подпрограмм.

Форма & подпрограмма также используется в так называемой форме магии goto .

Выражение goto &subroutine заменяет текущий контекст вызова вызовом именованной подпрограммы с использованием текущего значения @_.

По сути, вы можете полностью переключить вызов на одну подпрограмму с вызовом названного. Это обычно наблюдается в блоках AUTOLOAD, где может быть сделан запрос отложенной подпрограммы, возможно, с некоторой модификацией к @_, но он полностью смотрит на программу, как если бы это был вызов именованного элемента.

например

sub AUTOLOAD {
    ...
    push @_, @extra_args; # add more arguments onto the parameter list
    goto &subroutine ; # change call another subroutine, as if we were never here
}

}

Потенциально это может быть полезно для устранения хвостового вызова , я полагаю.

см. подробное объяснение этой методики здесь


IMO, единственный раз, когда есть какая-то причина для использования & - если вы получаете или называете coderef, например:

sub foo() {
    print "hi\n";
}

my $x = \&foo;
&$x();

Основное время, которое вы можете использовать, которое вы абсолютно не должны в большинстве случаев, - это вызов подпрограммы, у которой есть прототип, который указывает любое поведение по умолчанию, отличное от стандартного. Я имею в виду, что некоторые прототипы позволяют переинтерпретировать список аргументов, например, преобразование @array и %hash спецификаций в ссылки. Таким образом, sub будет ожидать, что эти переинтерпретации произойдут, и если вы не зайдете на любую длину, необходимую для имитации их вручную, sub получит входные данные, сильно отличающиеся от ожидаемых.

Я думаю, что в основном люди пытаются сказать вам, что вы все еще пишете в стиле Perl 4, и теперь у нас есть намного более чистая и приятная вещь под названием Perl 5.

Что касается производительности, существуют различные способы, которыми Perl оптимизирует подзаголовки, которые побеждают, причем одним из основных является инкрустация констант.

Существует также одно обстоятельство, в котором использование & дает преимущество в производительности: если вы переадресовываете подзаголовок с помощью foo(@_) . Использование &foo бесконечно быстрее, чем foo(@_) . Я бы не рекомендовал его, если вы окончательно не обнаружили путем профилирования, что вам нужна эта микро-оптимизация.


Я часто злоупотребляю & , но в основном потому, что я делаю странные вещи интерфейса. Если вам не нужна одна из этих ситуаций, не используйте & . Большинство из них - это просто доступ к определению подпрограммы, а не вызов подпрограммы. Это все в perlsub .

  1. Обращение к именованной подпрограмме. Вероятно, это единственная распространенная ситуация для большинства Perlers:

     my $sub = \&foo;
    
  2. Аналогично, присваивая typeglob, который позволяет вам вызвать подпрограмму с другим именем:

     *bar = \&foo;
    
  3. Проверка того, что подпрограмма определена, как вы можете в тестовых наборах:

     if( defined &foo ) { ... }
    
  4. Удаление определения подпрограммы, которое не должно быть общим:

     undef &foo;
    
  5. Предоставление диспетчерской подпрограммы, единственной задачей которой является выбор правильной подпрограммы для вызова. Это единственная ситуация, которую я использую & для вызова подпрограммы, и когда я ожидаю вызвать диспетчера много раз и вам нужно выжать небольшое количество из операции:

     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
  6. Чтобы перейти в другую подпрограмму, используя текущий стек аргументов (и заменив текущую подпрограмму в стеке вызовов), выполняется непрактичная операция при диспетчеризации, особенно в AUTOLOAD :

     goto ⊂
    
  7. Вызовите подпрограмму, которую вы назвали после встроенного Perl. Параметр & всегда дает вам пользовательский. Вот почему мы учим его в Learning Perl . Вы действительно не хотите делать это нормально, но это одна из особенностей & .

Есть места, где вы можете их использовать, но есть лучшие способы:

  1. Вызов подпрограммы с тем же именем, что и встроенный Perl. Просто не имеют подпрограмм с тем же именем, что и встроенный Perl. Проверьте perlfunc чтобы просмотреть список встроенных имен, которые вы не должны использовать.

  2. Чтобы отключить прототипы. Если вы не знаете, что это значит или почему вы хотите, не используйте & . Некоторый код черной магии может понадобиться, но в таких случаях вы, вероятно, знаете, что делаете.

  3. Развернуть и выполнить ссылку подпрограммы. Просто используйте нотацию -> .





subroutine