수색…


통사론

  • @enum EnumType val = 1 val val
  • :상징

비고

때로는 각 인스턴스가 다른 유형 (종종 싱글 톤 불변 유형 ) 인 열거 형을 갖는 것이 유용합니다. 이것은 유형 안정성에 중요 할 수 있습니다. 특성은 일반적으로이 패러다임으로 구현됩니다. 그러나 이로 인해 컴파일 시간 오버 헤드가 추가로 발생합니다.

열거 형 정의

열거 형 은 가능한 값의 유한 목록 중 하나를 보유 할 수있는 유형 입니다. Julia에서 열거 형은 일반적으로 "열거 형"이라고합니다. 예를 들어, 일주일 중 7 일, 12 개월, 표준 52 카드 데크 의 네 가지 슈트 또는 기타 유사한 상황을 설명하기 위해 enum 유형을 사용할 수 있습니다.

우리는 열거 형을 정의하여 표준 52 카드 덱의 수트와 랭크를 모델링 할 수 있습니다. @enum 매크로는 enum 유형을 정의하는 데 사용됩니다.

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

여기에는 SuitRank 두 가지 유형이 정의됩니다. 값이 실제로 예상되는 유형인지 확인할 수 있습니다.

julia> ♦
♦::Suit = 1

julia> six
six::Rank = 6

각 수트와 랭크는 숫자와 연관되어 있습니다. 기본적으로이 숫자는 0부터 시작합니다. 따라서 두 번째 수트 인 다이아몬드에는 1이 할당되었습니다. Rank 의 경우 하나에서 번호를 시작하는 것이 더 적합 할 수 있습니다. 이것은 a =1 주석이있는 ace 의 정의에 주석을 ace 얻을 수있었습니다.

열거 형에는 평등 (및 실제로 신원) 및 비교 기능과 같은 많은 기능이 있습니다.

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 로 변환 할 수 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 새로운 순위로 :eleven 을 받아들이 려한다면 push!(ranks, :eleven) 실행하기 만하면됩니다. 이러한 런타임 확장 성은 @enum 유형에서는 가능하지 않습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow