константа
СОДЕРЖАНИЕ
- ИМЯ
- СИНОПСИС
- ОПИСАНИЕ
- ПРИМЕЧАНИЯ
- ТЕХНИЧЕСКИЕ ПРИМЕЧАНИЯ
- ОГРАНИЧЕНИЯ
- СМОТРИТЕ ТАКЖЕ
- ОШИБКИ
- АВТОРЫ
- АВТОРСКИЕ ПРАВА И ЛИЦЕНЗИЯ
ИМЯ
constant - прагма Perl для объявления констант
СИНОПСИС
use constant PI => 4 * atan2(1, 1);
use constant DEBUG => 0;
print "Pi equals ", PI, "...\n" if DEBUG;
use constant {
SEC => 0,
MIN => 1,
HOUR => 2,
MDAY => 3,
MON => 4,
YEAR => 5,
WDAY => 6,
YDAY => 7,
ISDST => 8,
};
use constant WEEKDAYS => qw(
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
);
print "Today is ", (WEEKDAYS)[ (localtime)[WDAY] ], ".\n";
ОПИСАНИЕ
Эта прагма позволяет объявлять константы во время компиляции.
Когда вы объявляете константу, например PI, используя вышеуказанный метод, каждый компьютер, на котором выполняется ваш скрипт, может использовать столько цифр точности, сколько ему доступно. Кроме того, ваша программа будет легче читаться, ее легче будет поддерживать (и поддерживать корректно), и вероятность того, что она отправит космический зонд на неправильную планету, потому что никто не заметил одну формулу, в которой вы написали 3.14195, будет значительно ниже.
Когда константа используется в выражении, Perl заменяет ее значением во время компиляции и может далее оптимизировать выражение. В частности, любой код в блоке if (CONSTANT) будет исключен из оптимизации, если константа равна false.
ПРИМЕЧАНИЯ
Как и во всех use директивах, определение константы происходит во время компиляции. Поэтому, вероятно, неверно помещать объявление константы внутри условного оператора (например, if ($foo) { use constant ... }).
Константы, определенные с помощью этого модуля, не могут быть интерполированы в строки, как переменные. Однако конкатенация работает нормально:
print "Pi equals PI...\n"; # WRONG: does not expand "PI"
print "Pi equals ".PI."...\n"; # right
Даже если ссылка объявлена как константа, ссылка может указывать на данные, которые могут быть изменены, как показано в данном коде.
use constant ARRAY => [ 1,2,3,4 ];
print ARRAY->[1];
ARRAY->[1] = " be changed";
print ARRAY->[1];
Константы принадлежат тому пакету, в котором они определены. Чтобы обратиться к константе, определенной в другом пакете, укажите полное имя пакета, как в Some::Package::CONSTANT. Константы могут экспортироваться модулями и могут также вызываться как методы класса или экземпляра, то есть как Some::Package->CONSTANT или как $obj->CONSTANT, где $obj является экземпляром Some::Package. Подклассы могут определять свои собственные константы для переопределения констант базового класса.
Начиная с версии 1.32 этого модуля, константы могут быть определены в пакетах, отличных от вызывающего, путем включения имени пакета в имя константы:
use constant "OtherPackage::FWIBBLE" => 7865;
constant->import("Other::FWOBBLE",$value); # dynamically at run time
Использование заглавных букв для имён констант является просто конвенцией, хотя это рекомендуется для того, чтобы константы выделялись и для того, чтобы избежать конфликтов с другими ключевыми словами, именами подпрограмм и служебными словами. Имена констант должны начинаться с буквы или символа нижнего подчёркивания. Имена, начинающиеся с двух символов нижнего подчёркивания, зарезервированы. Некоторые неудачные имена будут генерировать предупреждения, если предупреждения включены во время компиляции.
Список констант
Константы могут быть списками из более (или менее) одного значения. Константа без значений в скалярном контексте оценивается как undef. Обратите внимание, что константы с более чем одним значением не возвращают последнее значение в скалярном контексте, как можно было бы ожидать. В настоящее время они возвращают количество значений, но это может измениться в будущем. Не используйте константы с несколькими значениями в скалярном контексте.
ПРИМЕЧАНИЕ: Это подразумевает, что выражение, определяющее значение константы, вычисляется в контексте списка. Это может привести к неожиданным результатам:
use constant TIMESTAMP => localtime; # WRONG!
use constant TIMESTAMP => scalar localtime; # right
Первая строка выше определяет TIMESTAMP как список из 9 элементов, как возвращается localtime() в контексте списка. Чтобы установить его в строку, возвращаемую localtime() в скалярном контексте, необходимо явно указать ключевое слово scalar.
Список констант — это списки, а не массивы. Для индексации или срезов их необходимо поместить в скобки.
my @workdays = WEEKDAYS[1 .. 5]; # WRONG!
my @workdays = (WEEKDAYS)[1 .. 5]; # right
Определение нескольких констант сразу
Вместо написания нескольких use constant операторов, вы можете определить несколько констант в одном операторе, передав вместо имени константы ссылку на хеш, где ключи — имена констант, которые нужно определить. Очевидно, что все константы, определенные этим методом, должны иметь одно значение.
use constant {
FOO => "A single value",
BAR => "This", "won't", "work!", # Error!
};
Это фундаментальное ограничение способа построения хешей в Perl. Сообщения об ошибках, генерируемые в таких случаях, часто бывают довольно загадочными — в худшем случае их может и не быть, и вы узнаете об ошибке только позже.
При определении нескольких констант вы не можете использовать значения других констант, определенных в том же объявлении. Это связано с тем, что вызывающий пакет не знает о константе внутри группы до после выполнения оператора use.
use constant {
BITMASK => 0xAFBAEBA8,
NEGMASK => ~BITMASK, # Error!
};
Магические константы
Магические значения и ссылки могут быть преобразованы в константы во время компиляции, что позволяет создавать очень интересные вещи, такие как это. (Эти номера ошибок не являются полностью переносимыми, к сожалению.)
use constant E2BIG => ($! = 7);
print E2BIG, "\n"; # something like "Arg list too long"
print 0+E2BIG, "\n"; # "7"
Вы не можете создать привязанную константу, передав привязанный скаляр в качестве значения. Однако ссылки на привязанные переменные могут использоваться как константы без каких-либо проблем.
ТЕХНИЧЕСКИЕ ПРИМЕЧАНИЯ
В текущей реализации скалярные константы фактически являются встраиваемыми подпрограммами. Начиная с версии 5.004 Perl, соответствующая скалярная константа вставляется непосредственно вместо некоторых вызовов подпрограмм, тем самым экономя накладные расходы вызова подпрограммы. См. "Constant Functions" в perlsub для получения подробной информации о том, как и когда это происходит.
В редких случаях, когда вам нужно обнаружить во время выполнения, была ли определена конкретная константа с помощью этого модуля, вы можете использовать эту функцию для проверки хеша %constant::declared. Если имя данной константы не содержит имени пакета, используется текущий пакет.
sub declared ($) {
use constant 1.01; # don't omit this!
my $name = shift;
$name =~ s/^::/main::/;
my $pkg = caller;
my $full_name = $name =~ /::/ ? $name : "${pkg}::$name";
$constant::declared{$full_name};
}
ОГРАНИЧЕНИЯ
Список констант не встраивается, если вы не используете Perl версии 5.20 или выше. В версиях 5.20 и выше они всё ещё не являются неизменяемыми, но это может измениться в будущих версиях.
В одном пакете не может быть подпрограммы или ключевого слова с тем же именем, что и константа. Вероятно, это хорошо.
Константа с именем в списке STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG не допускается нигде, кроме пакета main::, по техническим причинам.
В отличие от констант в некоторых языках, их нельзя переопределить в командной строке или через переменные среды.
Возможны проблемы, если вы используете константы в контексте, который автоматически приводит к цитированию свободных слов (как это происходит при любом вызове подпрограммы). Например, вы не можете сказать $hash{CONSTANT}, потому что CONSTANT будет интерпретироваться как строка. Используйте $hash{CONSTANT()} или $hash{+CONSTANT} для предотвращения срабатывания механизма цитирования свободных слов. Аналогично, поскольку оператор => цитирует свободный символ непосредственно слева от него, вы должны написать CONSTANT() => 'value' (или просто использовать запятую вместо большого знака стрелки) вместо CONSTANT => 'value'.
СМОТРИТЕ ТАКЖЕ
Readonly - средство для создания неизменяемых скаляров, массивов, хешей.
Attribute::Constant - создание неизменяемых переменных через атрибуты
Scalar::Readonly - расширение Perl для флага скалярного SvREADONLY.
Hash::Util - набор утилитарных подпрограмм хешей (в основном для блокировки/разблокировки ключей и значений)
ОШИБКИ
Пожалуйста, сообщайте об ошибках или пожеланиях по функционалу через утилиту perlbug(1).
АВТОРЫ
Том Феникс, <rootbeer@redcat.com>, с помощью многих других людей.
Определение нескольких констант одновременно добавлено Кэси Уэстом, <casey@geeknest.com>.
Документация в основном переписана Ильмари Каронен, <perl@itz.pp.sci.fi>.
Эта программа поддерживается носителями Perl 5. Распространение CPAN поддерживается Sebastien Aperghis-Tramoni <sebastien@aperghis.net>.
АВТОРСКИЕ ПРАВА И ЛИЦЕНЗИЯ
Авторские права (C) 1997, 1999 Том Феникс
Этот модуль является свободным программным обеспечением; вы можете перераспределять его или изменять его в соответствии с теми же условиями, что и Perl сам.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.32.0/constant