Zoeken…


Syntaxis

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

Opmerkingen

Het is soms handig om opgesomde typen te hebben waarbij elke instantie van een ander type is (vaak een onveranderlijk type van singleton ); dit kan belangrijk zijn voor typestabiliteit. Kenmerken worden doorgaans geïmplementeerd met dit paradigma. Dit resulteert echter in extra compilatie-overheadkosten.

Een opgesomd type definiëren

Een opgesomd type is een type dat een van een eindige lijst met mogelijke waarden kan bevatten. In Julia worden opgesomde typen meestal "opsommingstypes" genoemd. Je kunt bijvoorbeeld enum-typen gebruiken om de zeven dagen van de week, de twaalf maanden van het jaar, de vier kleuren van een standaard kaartspel met 52 kaarten of andere vergelijkbare situaties te beschrijven.

We kunnen opgesomde typen definiëren om de kleuren en rangen van een standaard kaartspel met 52 kaarten te modelleren. De macro @enum wordt gebruikt om enum-typen te definiëren.

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

Dit definieert twee soorten: Suit en Rank . We kunnen controleren of de waarden inderdaad van het verwachte type zijn:

julia> ♦
♦::Suit = 1

julia> six
six::Rank = 6

Merk op dat elke reeks en rang is gekoppeld aan een nummer. Standaard begint dit nummer bij nul. Dus de tweede reeks, diamanten, kreeg het nummer 1. In het geval van Rank kan het logischer zijn om het nummer met één te beginnen. Dit werd bereikt door de definitie van ace annoteren met een =1 annotatie.

Opgesomde types hebben veel functionaliteit, zoals gelijkheid (en inderdaad identiteit) en ingebouwde vergelijkingen:

julia> seven === seven
true

julia> ten ≠ jack
true

julia> two < three
true

Net als waarden van elk ander onveranderlijk type , kunnen waarden van opgesomde typen ook worden gehasht en opgeslagen in Dict s.

We kunnen dit voorbeeld te voltooien door het definiëren van een Card type zijn dat een heeft Rank en een Suit veld:

immutable Card
    rank::Rank
    suit::Suit
end

en daarom kunnen we kaarten maken met

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

Maar opgesomde typen komen ook met hun eigen convert , dus we kunnen dit inderdaad eenvoudig doen

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

en aangezien 7 direct kan worden omgezet in Rank , werkt deze constructor direct.

We willen misschien syntactische suiker definiëren voor het construeren van deze kaarten; impliciete vermenigvuldiging biedt een handige manier om dit te doen. Bepalen

julia> import Base.*

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

en toen

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

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

opnieuw gebruik makend van de ingebouwde convert functies.

Symbolen gebruiken als lichtgewicht enums

Hoewel de macro @enum vrij nuttig is voor de meeste gevallen, kan deze in sommige gevallen buitensporig zijn. Nadelen van @enum zijn onder meer:

  • Het creëert een nieuw type
  • Het is een beetje moeilijker om uit te breiden
  • Het wordt geleverd met functionaliteit zoals conversie, opsomming en vergelijking, die in sommige toepassingen overbodig kan zijn

In gevallen waarin een lichter alternatief gewenst is, kan het Symbol worden gebruikt. Symbolen zijn tekenreeksen ; ze vertegenwoordigen reeksen tekens, net zoals tekenreeksen , maar ze zijn uniek geassocieerd met getallen. Deze unieke associatie maakt een snelle vergelijking van symboolgelijkheid mogelijk.

We kunnen opnieuw een Card implementeren, dit keer met behulp van 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

We implementeren de interne constructor om te controleren op eventuele onjuiste waarden die aan de constructor zijn doorgegeven. In tegenstelling tot het voorbeeld dat @enum typen gebruikt, kan Symbol s elke tekenreeks bevatten en moeten we dus voorzichtig zijn met het soort Symbol we accepteren. Let hier op het gebruik van de voorwaardelijke kortsluitingsexploitanten .

Nu kunnen we bouwen Card voorwerpen zoals we verwachten:

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

Een groot voordeel van Symbol s is hun verlengbaarheid tijdens gebruik. Als we tijdens runtime (bijvoorbeeld) :eleven als een nieuwe rang willen accepteren, volstaat het om eenvoudig push!(ranks, :eleven) . Een dergelijke verlengbaarheid tijdens runtime is niet mogelijk met @enum typen.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow