Если Вы хотите иметь дело с различными числовыми условиями и хотеть обработать различные типы преобразований управляемым способом, то, возможно, необходимо посмотреть эти Повышение. 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;
}
IMO, единственная причина для использования и
- это получение или вызов coderef, например:
sub foo() {
print "hi\n";
}
my $x = \&foo;
&$x();
Основной раз, когда вы можете использовать его, но категорически не должны в большинстве случаев, это при вызове подпрограммы, у которой есть прототип, который задает любое поведение вызова не по умолчанию. Я имею в виду, что некоторые прототипы позволяют переинтерпретировать список аргументов, например преобразовать спецификации @array
и % hash
в ссылки. Таким образом, подводная лодка будет ожидать, что эти интерпретации произошли, и если вы не сделаете все возможное, чтобы имитировать их вручную, подпрограмма будет получать входные данные, сильно отличающиеся от ожидаемых.
Я думаю, что в основном люди пытаются сказать вам, что вы все еще пишете в стиле Perl 4, и теперь у нас есть гораздо более чистая и приятная вещь под названием Perl 5.
Что касается производительности, существуют различные способы, которыми Perl оптимизирует вспомогательные вызовы, которые &
побеждают, причем одним из основных является встраивание констант.
Существует также одно обстоятельство, при котором использование &
обеспечивает повышение производительности: если вы пересылаете вспомогательный вызов с помощью foo (@_)
. Использование & foo
бесконечно быстрее, чем foo (@_)
. Я бы не рекомендовал это, если вы окончательно не обнаружили в процессе профилирования, что вам нужна такая микрооптимизация.
Форма & 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
}
}
Потенциально это может быть полезно для исключения хвостовых вызовов , я полагаю.
Я частый нарушитель и
, но в основном потому, что я занимаюсь странными интерфейсами. Если вам не нужна одна из этих ситуаций, не используйте и
. Большинство из них предназначены только для доступа к определению подпрограммы, а не для ее вызова. Все это в perlsub .
Взятие ссылки на именованную подпрограмму. Это, вероятно, единственная распространенная ситуация для большинства Perler:
my $ sub = \ & foo;
Точно так же присваивается typeglob, что позволяет вызывать подпрограмму с другим именем:
* bar = \ & foo;
Проверка определения подпрограммы, как в тестовых наборах:
if (defined & foo) {...}
Удаление определения подпрограммы, которое не должно быть обычным:
undef & foo;
Обеспечение диспетчерской подпрограммы, единственная задача которой - выбрать правильную подпрограмму для вызова. Это единственная ситуация, в которой я использую &
для вызова подпрограммы, и когда я ожидаю, что диспетчер будет вызывать много-много раз и мне нужно немного снизить производительность операции:
sub figure_it_out_for_me {
# все это повторно использует текущий @_
if (... какое-то условие ...) {& foo}
elsif (... другой ...) {& bar}
else {& default}
}
Переход к другой подпрограмме с использованием текущего стека аргументов (и замена текущей подпрограммы в стеке вызовов), невыполненная операция диспетчеризации, особенно в AUTOLOAD
:
goto & sub;
Вызов подпрограммы, которую вы назвали в честь встроенного Perl. &
всегда дает вам определенный пользователем. Вот , почему мы учим его в Learning Perl . Обычно вы не хотите этого делать, но это одна из возможностей и
.
Есть несколько мест, где вы можете их использовать, но есть способы лучше:
Позвонить подпрограмма с тем же именем, что и встроенный Perl. Просто не создавайте подпрограмм с тем же именем, что и у встроенных Perl. Проверьте perlfunc , чтобы увидеть список встроенных имен, которые вы не должны использовать.
Чтобы отключить прототипы. Если вы не знаете, что это значит или почему вам это нужно, не используйте &
. Некоторому коду черной магии это может понадобиться, но в таких случаях вы, вероятно, знаете, что делаете.
Разыменовать и выполнить ссылку на подпрограмму. Просто используйте нотацию ->
.