Sök…


Syntax

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

Anmärkningar

Det är ibland användbart att ha uppräknade typer där varje instans är av en annan typ (ofta en singleton immutable typ ); detta kan vara viktigt för typstabilitet. Egenskaper implementeras vanligtvis med detta paradigm. Detta resulterar emellertid i extra kompileringstidskostnader.

Definiera en uppräknad typ

En uppräknad typ är en typ som kan innehålla en av en begränsad lista över möjliga värden. I Julia kallas uppräknade typer vanligtvis "enumtyper". Till exempel kan man använda enumtyper för att beskriva de sju dagarna i veckan, årets tolv månader, de fyra kostymerna på ett standardkort med 52 kort eller andra liknande situationer.

Vi kan definiera uppräknade typer för att modellera dräkter och rangordningar för ett standarddäck med 52 kort. @enum används för att definiera enumtyper.

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

Detta definierar två typer: Suit och Rank . Vi kan kontrollera att värdena verkligen är av de förväntade typerna:

julia> ♦
♦::Suit = 1

julia> six
six::Rank = 6

Observera att varje färg och rang har kopplats till ett nummer. Som standard börjar detta nummer med noll. Så den andra dräkten, diamanter, tilldelades numret 1. I fallet med Rank kan det vara mer meningsfullt att starta numret på ett. Detta uppnåddes genom att kommentera definitionen av ace med en =1 kommentar.

Uppräknade typer har mycket funktionalitet, såsom jämlikhet (och faktiskt identitet) och jämförelser inbyggda:

julia> seven === seven
true

julia> ten ≠ jack
true

julia> two < three
true

Liksom värden av någon annan immutabel typ kan värden på uppräknade typer också hashas och lagras i Dict s.

Vi kan slutföra detta exempel genom att definiera en Card som har ett Rank och Suit :

immutable Card
    rank::Rank
    suit::Suit
end

och därmed kan vi skapa kort med

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

Men uppräknade typer har också sina egna convert , så vi kan verkligen bara göra det

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

och eftersom 7 kan konverteras direkt till Rank , fungerar denna konstruktör ut ur lådan.

Vi kanske vill definiera syntaktiskt socker för att konstruera dessa kort; implicit multiplikation ger ett bekvämt sätt att göra det. Definiera

julia> import Base.*

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

och då

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

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

återigen utnyttja de inbyggda convert .

Använda symboler som lätta enums

Även om @enum är ganska användbar för de flesta användningsfall, kan det vara överdrivet i vissa användningsfall. Nackdelarna med @enum inkluderar:

  • Det skapar en ny typ
  • Det är lite svårare att förlänga
  • Det kommer med funktionalitet som konvertering, uppräkning och jämförelse, vilket kan vara överflödigt i vissa applikationer

I fall där ett lättare alternativ önskas kan Symbol användas. Symboler är internerade strängar ; de representerar sekvenser av karaktärer, ungefär som strängar gör, men de är unikt associerade med siffror. Denna unika förening möjliggör snabb jämförelse av symboler.

Vi kan åter implementera en Card , den här gången med 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

Vi implementerar den inre konstruktören för att kontrollera om felaktiga värden överförs till konstruktören. Till skillnad från i exemplet med hjälp av @enum typer Symbol kan s innehålla någon sträng, och därför måste vi vara försiktiga med vilka typer av Symbol s vi accepterar. Notera här användningen av kortslutna villkorade operatörer.

Nu kan vi konstruera Card som vi förväntar oss:

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

En viktig fördel med Symbol är deras extensionsutdragbarhet. Om vi vid körning vill acceptera (till exempel) :eleven som en ny rang, räcker det för att helt enkelt köra push!(ranks, :eleven) . Sådan runtime-utdragbarhet är inte möjlig med @enum .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow