web-dev-qa-db-ja.com

Perlには列挙型がありますか?

Perlには、ベストプラクティスを順守する列挙型がありますか、またはもっと重要な場合、それが必要ですか?

私が取り組んでいるプロジェクトでは、C#のような言語で通常Enumを使用することを示すために、あらゆる場所で文字列を使用しています。たとえば、ハッシュの配列に一連の電話番号があり、それぞれが電話の種類( "Home"、 "Work"、 "Mobile"など)に関連付けられています。

$phone_number->{type} = 'Home';

ここで読み取り専用の変数セットを使用するだけで十分ですか、それともEnumを使用する必要がありますか? CPANのenumモジュール を見つけましたが、 Perl Best Practices のいずれかに違反するむき出しの単語を使用しているようです。 読み取り専用変数 の使用に関する私の考えは次のようになります。

use Readonly;

Readonly my $HOME   => 'Home';
Readonly my $WORK   => 'Work';
Readonly my $MOBILE => 'Mobile';

$phone_number->{type} = $HOME;

これは良いアプローチですか、それとももっと良い方法がありますか?

57
cowgod

いいえ、組み込みの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";
44
Ronald Blaschke

実際、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はサポートしていることを知っています。

24
Nathan Fellman

Perlはこの概念をネイティブにサポートしていませんが、この機能を追加するモジュールがあります

https://metacpan.org/pod/enum

11
Ray Booysen

あなたの方法は十分すぎるほどです。

Mooseを使用している場合は、Moose :: Util :: TypeConstraintsを使用して列挙型を作成することもできます。 (あなたはそうあるべきです。)

8
jrockway

これらの列挙型と名前付き定数に関しては、Perlは完全に対麻痺していると思います。

  • enumとReadonlyはコアモジュールではありません(少なくともPerl 5.8ではチェックしました)。したがって、新しいモジュールをインストールする自由がないシステムでは、これらは利用できない場合があります。

  • 「use strict」と「use strict」(常に使用する必要があります)は、次の形式の恐ろしいエラーメッセージを大量に生成するため、まったく使用できません。

    ベアワード「FRED」は「strict subs」の使用中は許可されません

Perl 6でこの混乱を解決したことを願っています。

5
John Roberts

これは私にとってうまくいった...

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

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

その後、ZERO, ONE, TWOなどを定数として使用し、(MYENUM)[$value]を使用してそのシンボリック名を出力できます。

0
kbro