Suche…


Syntax

  • @enum EnumType val = 1 val val
  • :Symbol

Bemerkungen

Es ist manchmal nützlich, Aufzählungstypen zu haben, bei denen jede Instanz einen anderen Typ hat (häufig ein unveränderlicher Singleton-Typ ). Dies kann für die Typstabilität wichtig sein. Merkmale werden typischerweise mit diesem Paradigma implementiert. Dies führt jedoch zu zusätzlichem Aufwand für die Kompilierung.

Einen Aufzählungstyp definieren

Ein Aufzählungstyp ist ein Typ , der eine endliche Liste möglicher Werte enthalten kann. In Julia werden Aufzählungstypen normalerweise "Aufzählungstypen" genannt. Zum Beispiel könnte man Aufzählungstypen verwenden, um die sieben Tage der Woche, die zwölf Monate des Jahres, die vier Farben eines Standard-Decks mit 52 Karten oder andere ähnliche Situationen zu beschreiben.

Wir können aufgezählte Typen definieren, um die Anzüge und Ränge eines Standard-Decks mit 52 Karten zu modellieren. Das @enum enum-Makro wird zur Definition von Aufzählungstypen verwendet.

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

Dies definiert zwei Typen: Suit und Rank . Wir können überprüfen, ob die Werte tatsächlich den erwarteten Typen entsprechen:

julia> ♦
♦::Suit = 1

julia> six
six::Rank = 6

Beachten Sie, dass jeder Farbe und Rang eine Nummer zugeordnet wurde. Standardmäßig beginnt diese Nummer bei Null. Daher wurde der zweiten Farbe, Diamanten, die Nummer 1 zugewiesen. Im Fall von Rank kann es sinnvoller sein, die Nummer bei eins zu beginnen. Dies wurde durch Annotation der Definition von ace mit einer Annotation =1 .

Aufzählungsarten verfügen über eine Vielzahl von Funktionen, z. B. Gleichheit (und sogar Identität) und integrierte Vergleiche:

julia> seven === seven
true

julia> ten ≠ jack
true

julia> two < three
true

Wie Werte eines anderen unveränderlichen Typs können auch Werte von aufgezählten Typen in Dict gespeichert und gespeichert werden.

Wir können dieses Beispiel vervollständigen, indem Sie einen Card definieren, der ein Feld für Rank und ein Feld für Suit :

immutable Card
    rank::Rank
    suit::Suit
end

und somit können wir Karten mit erstellen

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

Aufzählungsarten verfügen jedoch auch über eigene convert , sodass wir dies in der Tat tun können

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

Da 7 direkt in Rank konvertiert werden kann, ist dieser Konstruktor sofort einsatzbereit.

Wir möchten möglicherweise syntaktischen Zucker für die Konstruktion dieser Karten definieren. Die implizite Multiplikation bietet eine bequeme Möglichkeit, dies zu tun. Definieren

julia> import Base.*

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

und dann

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

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

wieder die eingebauten convert .

Verwendung von Symbolen als leichtes Enum

Obwohl das @enum Makro für die meisten Anwendungsfälle recht nützlich ist, kann es in einigen Anwendungsfällen übermäßig sein. Nachteile von @enum sind:

  • Es wird ein neuer Typ erstellt
  • Es ist etwas schwieriger zu erweitern
  • Sie bietet Funktionen wie Konvertierung, Aufzählung und Vergleich, die in manchen Anwendungen überflüssig sein können

Wenn eine leichtere Alternative gewünscht wird, kann der Symbol verwendet werden. Symbole sind interne Zeichenfolgen . Sie stellen Zeichenfolgen dar, ähnlich wie Zeichenfolgen , aber sie sind eindeutig mit Zahlen verknüpft. Diese einzigartige Zuordnung ermöglicht einen schnellen Vergleich der Symbolgleichheit.

Wir können einen Card erneut implementieren, diesmal mit Symbol :

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

Wir implementieren den inneren Konstruktor, um zu überprüfen, ob falsche Werte an den Konstruktor übergeben werden. Anders als in dem Beispiel, in dem @enum Typen verwendet werden, können Symbol eine beliebige Zeichenfolge enthalten. @enum müssen wir darauf achten, welche Arten von Symbol wir akzeptieren. Beachten Sie hier die Verwendung der bedingten Kurzschlussoperatoren .

Jetzt können wir Card Objekte wie erwartet 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

Ein großer Vorteil von Symbol ist die Laufzeiterweiterung. Wenn wir zur Laufzeit (zum Beispiel) :eleven als neuen Rang akzeptieren möchten, genügt es, einfach push!(ranks, :eleven) auszuführen. Eine solche Laufzeiterweiterung ist bei @enum Typen nicht möglich.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow