Есть ли в Perl тип перечисления?

51

Имеет ли 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;

Это хороший подход или есть лучший способ?

  • 0
    Вы всегда должны помнить, что PBP носит рекомендательный характер - сама книга. Вы должны интерпретировать руководящие принципы, а не рабски принимать их.
Теги:
enums

7 ответов

38
Лучший ответ

Нет, нет встроенной конструкции 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";
  • 0
    Для строгости, за сценой есть sub HOME () {'home'}.
  • 0
    Когда у вас есть подпрограмма, которая принимает перечисление Phone :: Type в качестве аргумента, как вы выполняете динамическую проверку аргумента подпрограммы, это Phone :: Type type enum, а не string, not number ...
Показать ещё 5 комментариев
16

Perl действительно имеет тип перечисления, как в C. Попробуйте это для деталей.

perldoc enum

Например:

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 делает.

  • 9
    Поскольку я могу сказать, что use enum является модулем CPAN, а не частью основного языка.
  • 2
    @ Пол Нейтан ... Я не уверен, что это должно препятствовать тому, чтобы кто-то использовал это все же. Огромное количество возможностей Perl не являются частью ядра.
Показать ещё 1 комментарий
10

Perl не поддерживает концепцию изначально, но есть модули для добавления этой функции

https://metacpan.org/pod/enum

8

Ваш путь более чем адекватен.

Вы также можете создавать перечисления с Moose:: Util:: TypeConstraints, если вы используете Moose. (Который должен быть.)

5

Я боюсь, что perl полностью параплегирует, когда дело доходит до этих перечислений и названных констант:

  • enum и Readonly не являются основными модулями (по крайней мере, на perl 5.8, которые я только что проверил). Таким образом, они могут быть недоступны в системе, где нет никакой свободы в установке новых модулей.

  • "Использовать константу" с "use strict" (который всегда следует использовать) полностью непригодна, поскольку он генерирует нагрузку ужасных сообщений об ошибке формы:

    Невозможно использовать слово "FRED" во время использования "строгих подсетей"

Пусть надеются, что они разобрали этот беспорядок в perl 6, если это когда-нибудь увидит свет дня!

  • 2
    Константы не выводят предупреждения, и в 5.8 тоже не печатали: 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 и никаких предупреждений. (Да, я понимаю, что этому ответу уже несколько лет ...)
2

Вы всегда должны помнить, что PBP является рекомендательным - сама книга такая же. Вам нужно интерпретировать руководящие принципы, а не рабски принимать их.

0

Это сработало для меня...

use constant MYENUM => qw(ZERO ONE TWO THREE FOUR);

BEGIN {
    eval "use constant (MYENUM)[$_] => $_;" foreach 0..(MYENUM)-1;
}

Затем вы можете использовать ZERO, ONE, TWO и т.д. в качестве констант и распечатать свое символическое имя с помощью (MYENUM)[$value].

Ещё вопросы

Сообщество Overcoder
Наверх
Меню