Имеет ли Perl тип перечисления, который придерживается лучших практик или, что еще важнее, нуждается ли он в этом?
В проекте, в котором я работаю, все строки используются для обозначения вещей, которые обычно используют Enum на языке С#. Например, у нас есть набор телефонных номеров в массиве хэшей, каждый из которых связан с типом телефона ( "Главная", "Работа", "Мобильный" и т.д.):
$phone_number->{type} = 'Home';
Достаточно ли использовать здесь переменные только для чтения или использовать Enum? Я нашел модуль enum
в CPAN, но он, похоже, использует голые слова, которые нарушают один из Perl Best Practices. Мое мышление об использовании переменных только для чтения выглядит примерно так:
use Readonly;
Readonly my $HOME => 'Home';
Readonly my $WORK => 'Work';
Readonly my $MOBILE => 'Mobile';
$phone_number->{type} = $HOME;
Это хороший подход или есть лучший способ?
Нет, нет встроенной конструкции enum. Perl не делает много строгой типизации, поэтому я думаю, что на самом деле мало чего нужно.
На мой взгляд, используемый Readonly
прочный.
Также существует более традиционная constant
прагма.
use constant {
HOME => 'Home',
WORK => 'Work',
MOBILE => 'Mobile',
};
$phone_number->{type} = HOME;
За кулисами он устанавливает функцию для каждой константы, которая возвращает значение, например.
sub HOME () { 'Home' }
Я бы придерживался Readonly
, если вы не хотите использовать это свойство, например:
package Phone::Type;
use constant {
HOME => 'Home',
#...
};
package main;
print Phone::Type->HOME, "\n";
Perl действительно имеет тип перечисления, как в C. Попробуйте это для деталей.
Например:
use enum qw(HOME WORK MOBILE);
Теперь мы имеем:
HOME == 0
WORK == 1
MOBILE == 2
Вы также можете самостоятельно установить индексы:
use enum qw(HOME=0 WORK MOBILE=10 FAX);
Теперь мы имеем:
HOME == 0
WORK == 1
MOBILE == 10
FAX == 11
Посмотрите здесь для более подробной информации.
Обратите внимание, что это не поддерживается в каждой версии Perl. Я знаю, что v5.8.3 не поддерживает его, в то время как v5.8.7 делает.
use enum
является модулем CPAN, а не частью основного языка.
Perl не поддерживает концепцию изначально, но есть модули для добавления этой функции
Ваш путь более чем адекватен.
Вы также можете создавать перечисления с Moose:: Util:: TypeConstraints, если вы используете Moose. (Который должен быть.)
Я боюсь, что perl полностью параплегирует, когда дело доходит до этих перечислений и названных констант:
enum и Readonly не являются основными модулями (по крайней мере, на perl 5.8, которые я только что проверил). Таким образом, они могут быть недоступны в системе, где нет никакой свободы в установке новых модулей.
"Использовать константу" с "use strict" (который всегда следует использовать) полностью непригодна, поскольку он генерирует нагрузку ужасных сообщений об ошибке формы:
Невозможно использовать слово "FRED" во время использования "строгих подсетей"
Пусть надеются, что они разобрали этот беспорядок в perl 6, если это когда-нибудь увидит свет дня!
perl -e 'use strict qw(subs); use constant FRED => q{fred}; printf qq{Perl %vd\nConstant is %s\n}, $^V, FRED'
дает Perl 5.8.4 Constant is fred
и никаких предупреждений. (Да, я понимаю, что этому ответу уже несколько лет ...)
Вы всегда должны помнить, что PBP является рекомендательным - сама книга такая же. Вам нужно интерпретировать руководящие принципы, а не рабски принимать их.
Это сработало для меня...
use constant MYENUM => qw(ZERO ONE TWO THREE FOUR);
BEGIN {
eval "use constant (MYENUM)[$_] => $_;" foreach 0..(MYENUM)-1;
}
Затем вы можете использовать ZERO, ONE, TWO
и т.д. в качестве констант и распечатать свое символическое имя с помощью (MYENUM)[$value]
.