Когда я должен использовать и назвать подпрограмму Perl?

Если Вы хотите иметь дело с различными числовыми условиями и хотеть обработать различные типы преобразований управляемым способом, то, возможно, необходимо посмотреть эти Повышение. NumericConversion. Эта библиотека позволяет обрабатывать странные случаи (как из диапазона, округление, диапазоны, и т.д.)

Вот пример из документации:

#include 
#include 

int main() {

    typedef boost::numeric::converter Double2Int ;

    int x = Double2Int::convert(2.0);
    assert ( x == 2 );

    int y = Double2Int()(3.14); // As a function object.
    assert ( y == 3 ) ; // The default rounding is trunc.

    try
    {
        double m = boost::numeric::bounds::highest();
        int z = Double2Int::convert(m); // By default throws positive_overflow()
    }
    catch ( boost::numeric::positive_overflow const& )
    {
    }

    return 0;
}

48
задан brian d foy 20 June 2012 в 23:40
поделиться

3 ответа

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

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

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

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

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

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

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

36
ответ дан 26 November 2019 в 18:39
поделиться

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

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

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

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

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

По сути, вы можете полностью переключить вызов одной подпрограммы вызовом названной. Это обычно наблюдается в блоках 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
}

}

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

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

18
ответ дан 26 November 2019 в 18:39
поделиться

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

  1. Взятие ссылки на именованную подпрограмму. Это, вероятно, единственная распространенная ситуация для большинства Perler:

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

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

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

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

      sub figure_it_out_for_me {
     # все это повторно использует текущий @_
     if (... какое-то условие ...) {& foo} 
     elsif (... другой ...) {& bar}
     else {& default}
     }
    
  6. Переход к другой подпрограмме с использованием текущего стека аргументов (и замена текущей подпрограммы в стеке вызовов), невыполненная операция диспетчеризации, особенно в AUTOLOAD :

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

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

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

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

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

52
ответ дан 26 November 2019 в 18:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: