Как я могу встроить подпрограммы Perl? - PullRequest
9 голосов
/ 02 ноября 2010

Я читаю Code Complete 2 , и один из упомянутых моментов касается создания подпрограмм даже для операций, которые кажутся слишком простыми, чтобы иметь свои собственные подпрограммы, и как это можнополезно.

Я знаю, что могу встроить функции в C и C ++ , используя ключевое слово inline.Но я никогда не сталкивался с способом встроенных подпрограмм в Perl.

Есть ли способ указать интерпретатору Perl встроить вызовы подпрограмм (или почему нет)?

Ответы [ 4 ]

23 голосов
/ 02 ноября 2010

Подпрограммы-константы, то есть подпрограммы с пустым прототипом и постоянным возвращаемым значением, являются встроенными. Вот как прагма constant определяет константы:

sub five() { 5 }

будет встроен, если его увидят до первого использования.

В противном случае Perl позволяет динамически переопределять подпрограммы во время выполнения, поэтому вставка не подходит.

Для подпрограмм, которые всегда возвращают одно и то же значение при одинаковых входных данных, вы можете использовать memoization .

Глава 13 программирования Perl предоставляет некоторую информацию о шагах по оптимизации, предпринятых perl.

Это называется постоянным складыванием. Постоянное свертывание не ограничивается простыми случаями, такими как превращение 2 ** 10 в 1024 во время компиляции. Он также разрешает вызовы функций - как встроенные, так и объявленные пользователем подпрограммы, которые соответствуют критериям из раздела «Встроенные функции констант» в главе 6 «Подпрограммы». Напоминая о печально известном знании компиляторами FORTRAN собственных встроенных функций, Perl также знает, какие из своих встроенных функций следует вызывать во время компиляции. Вот почему, если вы попытаетесь получить лог 0.0 или sqrt отрицательной константы, вы получите ошибку компиляции, а не ошибку времени выполнения, и интерпретатор никогда не будет запущен вообще.

См. Также perldoc perlguts .

Вы можете увидеть эффект постоянного сворачивания самостоятельно:

#!/usr/bin/perl

use strict; use warnings;

sub log_ok () { 1 }

if ( log_ok ) {
    warn "log ok\n";
}
perl -MO=Deparse t.pl

Выход:

sub log_ok () { 1 }
use warnings;
use strict 'refs';
do {
    warn "log ok\n"
};
t.pl syntax OK

Здесь постоянное сворачивание привело к замене блока if на блок do, поскольку компилятор знал, что log_ok всегда будет возвращать истинное значение. С другой стороны, с:

#!/usr/bin/perl

use strict; use warnings;

sub log_ok () { 0.5 > rand }

if ( log_ok ) {
    warn "log ok\n";
}

Разбавить вывод:

sub log_ok () {
    use warnings;
    use strict 'refs';
    0.5 > rand;
}
use warnings;
use strict 'refs';
if (log_ok) {
    warn "log ok\n";
}
t.pl syntax OK

Компилятор C мог бы заменить if (log_ok) на if ( 0.5 > rand ). perl не делает этого.

5 голосов
/ 02 ноября 2010

Perl позволяет только встроить постоянные функции.От perldoc perlsub :

Функции с прототипом () являются потенциальными кандидатами для встраивания.Если результат после оптимизации и сложения констант является скаляром с постоянной или лексической областью, который не имеет других ссылок, он будет использоваться вместо вызовов функций, выполненных без &.

3 голосов
/ 02 ноября 2010

Я не пробовал ничего из этого, но если у вас есть время, вы можете попробовать

  1. Macro
  2. macro
  3. или даже Filter::Macro

Все они являются исходными фильтрами, поэтому вам придется проверить окупаемость инвестиций в производительность,Последний действительно имеет обзор cpanratings .(Не обращайте внимания на попытку Дана Дакалеску регулировать «воздушное пространство» модуля Perl.)

- На самом деле , последний Filter::Macro использует Filter::Simple::Compile (который, в свою очередь, использует Module::Compile) для компиляции подпрограмм, поэтому этот может работать выше других методов фильтра источника.Но применяются стандартные предупреждения для исходных фильтров .

1 голос
/ 03 ноября 2010

Скорость, вероятно, не должна учитываться при написании Perl.Идите вперед и заставьте вещи функционировать.Если профилирование позже показывает, что вы тратите много времени на выполнение простой функции из-за ее многократного вызова, вставьте эту функцию самостоятельно.

...