Julia Language
Aufzählungen
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.