サーチ…


構文

  • @enum EnumType val = 1 val val
  • :シンボル

備考

それぞれのインスタンスが異なる型(たいていはシングルトンの不変型 )の列挙型を持つことは、時には便利です。これは型の安定性にとって重要であり得る。形質は、典型的にはこのパラダイムで実施される。ただし、コンパイル時にオーバーヘッドが発生します。

列挙型の定義

列挙型は、可能な値の有限リストの1つを保持できるです。 Juliaでは、列挙型は通常「列挙型」と呼ばれます。例えば、7日間の曜日、12ヶ月の年月、 標準の52枚のカードデッキの4つの服、または他の同様の状況を記述するために列挙型を使用できます。

列挙型を定義して、標準的な52枚のカードデッキのスーツとランクをモデル化することができます。 @enumマクロは列挙型を定義するために使用されます。

@enum Suit ♣ ♦ ♥ ♠
@enum Rank ace=1 two three four five six seven eight nine ten jack queen king

これは、 SuitRank 2つのタイプを定義します。値が実際に予想される型であることを確認できます。

julia> ♦
♦::Suit = 1

julia> six
six::Rank = 6

各スーツとランクは数字に関連付けられていることに注意してください。デフォルトでは、この番号は0から始まります。したがって、第2スーツのダイヤモンドには1番の番号が割り当てられました。 Rankの場合は、番号を1番から始めるほうが意味があります。これは、 aceの定義にa =1アノテーションを付けることによって達成されました。

列挙型には、等価(実際には同一性)や組み込みのような多くの機能があります。

julia> seven === seven
true

julia> ten ≠ jack
true

julia> two < three
true

他の不変型の値と同様に、列挙型の値をハッシュしてDict格納することもできます。

RankSuitフィールドを持つCardタイプを定義して、この例を完成させることができます:

immutable Card
    rank::Rank
    suit::Suit
end

それで、私たちは

julia> Card(three, ♣)
Card(three::Rank = 3,♣::Suit = 0)

しかし、列挙型には独自のconvertメソッドも付属しているので、単純に行うことができます

julia> Card(7, ♠)
Card(seven::Rank = 7,♠::Suit = 3)

7は直接Rankに変換できるため、このコンストラクタはそのまま使用できます。

これらのカードを作るために構文的な砂糖を定義したいかもしれません。暗黙の乗算はそれを行うための便利な方法を提供します。定義する

julia> import Base.*

julia> r::Int * s::Suit = Card(r, s)
* (generic function with 156 methods)

その後

julia> 10♣
Card(ten::Rank = 10,♣::Suit = 0)

julia> 5♠
Card(five::Rank = 5,♠::Suit = 3)

もう一度内蔵のconvert関数を利用しています。

軽量列挙型としてのシンボルの使用

@enumマクロはほとんどのユースケースで非常に便利ですが、ユースケースによっては過剰になることがあります。 @enum短所は@enumとおりです。

  • 新しいタイプが作成されます
  • それは少し難しいです
  • それには、変換、列挙、比較などの機能が付属しているため、一部のアプリケーションでは不要です

より軽量の代替が望まれる場合、 Symbolタイプを使用することができる。シンボルは文字列で保持されます 。それらは文字列と同様に文字列を表しますが、数値と一意に関連付けられています。この独自の関連付けにより、シンボルの等価性を高速に比較できます。

今回は、 Symbolフィールドを使用してCardタイプを再度実装することができます:

const ranks = Set([:ace, :two, :three, :four, :five, :six, :seven, :eight, :nine,
                   :ten, :jack, :queen, :king])
const suits = Set([:♣, :♦, :♥, :♠])
immutable Card
    rank::Symbol
    suit::Symbol
    function Card(r::Symbol, s::Symbol)
        r in ranks || throw(ArgumentError("invalid rank: $r"))
        s in suits || throw(ArgumentError("invalid suit: $s"))
        new(r, s)
    end
end

内部コンストラクタを実装して、コンストラクタに渡された不正な値をチェックします。 @enum型を使用する例とは異なり、 Symbolは任意の文字列を含めることができるため、受け入れるSymbolの種類に注意する必要があります。ここでは、 短絡条件演算子の使用に注意してください。

今度は期待どおりのCardオブジェクトを構築できます:

julia> Card(:ace, :♦)
Card(:ace,:♦)

julia> Card(:nine, :♠)
Card(:nine,:♠)

julia> Card(:eleven, :♠)
ERROR: ArgumentError: invalid rank: eleven
 in Card(::Symbol, ::Symbol) at ./REPL[17]:5

julia> Card(:king, :X)
ERROR: ArgumentError: invalid suit: X
 in Card(::Symbol, ::Symbol) at ./REPL[17]:6

Symbolの主な利点は、実行時の拡張性です。実行時に(例えば) :elevenを新しいランクとして受け入れる場合は、 push!(ranks, :eleven) rank push!(ranks, :eleven)実行するだけで十分です。このような実行時の拡張性は、 @enum型では@enumです。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow