구조체 타입 속성

구조체 타입 속성 (Structure Type Properties)

구조체 타입 속성(structure type property)은 구조체 타입마다 정보를 연결하는 메커니즘이에요. 구조체 타입 속성 위에 높은 수준의 API를 제공하는 것이 제네릭 인터페이스(Generic Interfaces)예요.

출처: Racket Reference

본문

구조체 타입 속성은 구조체 타입(구조체 값 하나에 연결되는 인스턴스별 정보와는 대비되는)에 타입별 정보를 연결할 수 있게 해요. 속성 값은 make-struct-type 프로시저(구조체 타입 만들기 참고)나 struct#:property 옵션을 통해 구조체 타입에 연결돼요. 하위 타입은 부모 타입의 속성 값을 상속하며, 하위 타입은 상속된 속성 값을 새 값으로 재정의할 수 있어요.

(make-struct-type-property name
                           [guard
                            supers
                            can-impersonate?
                            accessor-name
                            contract-str
                            realm])
  → struct-type-property?
  (any/c . -> . boolean?)
  procedure?
  name : symbol?
  guard : (or/c procedure? #f 'can-impersonate) = #f
  supers : (listof (cons/c struct-type-property?
                           (any/c . -> . any/c))) = null
  can-impersonate? : any/c = #f
  accessor-name : (or/c symbol? #f) = #f
  contract-str : (or/c string? symbol? #f) = #f
  realm : symbol? = 'racket

새 구조체 타입 속성을 만들고 세 개의 값을 반환해요.

  • 구조체 타입 속성 기술자(descriptor). make-struct-typestruct와 함께 쓴다.
  • 속성 술어 프로시저. 임의의 값을 받아, 그 값이 그 속성에 대한 값을 가진 구조체 타입의 기술자나 인스턴스이면 #t, 아니면 #f를 반환한다.
  • 속성 접근자 프로시저. 구조체 타입의 기술자나 그 인스턴스 중 하나가 주어졌을 때 그 구조체 타입에 연결된 값을 반환한다. 구조체 타입이 그 속성에 대한 값을 갖고 있지 않거나, 다른 종류의 값이 제공되면, 프로시저에 두 번째 인자 failure-result가 제공되지 않는 한 exn:fail:contract 예외가 발생한다. 그 경우 failure-result가 프로시저라면 (꼬리 호출로) 인자 없이 호출되어 속성 접근자 프로시저의 결과를 만들어내고, 그렇지 않으면 failure-result 자체가 결과로 반환된다.

선택적 guard가 프로시저로 제공되면, make-struct-type이 새 구조체 타입에 속성을 붙이기 전에 그것을 호출해요. guard는 두 인자를 받아야 해요: make-struct-type에 제공된 속성 값, 그리고 새 구조체 타입에 대한 정보를 담은 목록. 그 목록에는 struct-type-infocurrent-inspector 제어 검사를 건너뛰었을 때 새 구조체 타입에 대해 반환할 값들이 담겨요.

guard를 호출한 결과가 make-struct-type에 제공된 값 대신 대상 구조체 타입에서 그 속성에 연결돼요. 속성 연결을 거부하려면(예: make-struct-type에 제공된 값이 그 속성에 부적절한 경우) guard가 예외를 발생시킬 수 있어요. 그런 예외는 make-struct-type이 구조체 타입 기술자를 반환하지 못하게 해요.

guard'can-impersonate면, 그 속성의 접근자는 impersonate-struct를 통해 리다이렉션될 수 있어요. 이 옵션은 can-impersonate? 인자로 #t를 제공하는 것과 동일하며, 하위 호환성을 위해 제공돼요.

선택적 supers 인자는, 새로 만들어진 속성이 어떤 구조체 타입에 연결될 때 그 구조체 타입에 자동으로 연결되는 속성들의 목록이에요. supers의 각 속성은, 새 속성에 제공된 값(guard로 처리된 후)을 받아 연결된 속성에 대한 값(그러면 그 속성의 가드(있으면)로 보내짐)을 반환하는 프로시저와 짝을 이뤄요.

선택적 can-impersonate? 인자는 구조체 타입 속성이 impersonate-struct를 통해 리다이렉션될 수 있는지 결정해요. 인자가 #f라면 리다이렉션이 허용되지 않아요. 그렇지 않으면 구조체 임포스터(impersonator)가 속성 접근자를 리다이렉션할 수 있어요.

선택적 accessor-name 인자는 반환된 접근자 함수에 쓸 이름(object-name의 의미에서)을 제공해요. accessor-name#fname의 끝에 -accessor를 붙여 이름을 만들어요.

선택적 contract-str 인자는, 반환된 접근자를 속성 인스턴스가 아닌 값에 적용했을 때(그리고 failure-result 인자가 접근자에 제공되지 않았을 때) 오류 메시지에 포함되는 계약(contract)을 제공해요. contract-str#fname의 끝에 ?를 붙여 계약을 만들어요.

선택적 realm 인자는 반환된 접근자와 연결할 영역(realm, procedure-realm의 의미에서)을 제공해요.

예제:

> (define-values (prop:p p? p-ref) (make-struct-type-property 'p))
> (define-values (struct:a make-a a? a-ref a-set!)
    (make-struct-type 'a #f 2 1 'uninitialized
                      (list (cons prop:p 8))))
> (p? struct:a)
#t
> (p? 13)
#f
> (define an-a (make-a 'x 'y))
> (p? an-a)
#t
> (p-ref an-a)
8
> (define-values (struct:b make-b b? b-ref b-set!)
    (make-struct-type 'b #f 0 0 #f))
> (p? struct:b)
#f
> (define-values (prop:q q? q-ref) (make-struct-type-property
                                    'q (lambda (v si) (add1 v))
                                    (list (cons prop:p sqrt))))
> (define-values (struct:c make-c c? c-ref c-set!)
    (make-struct-type 'c #f 0 0 'uninit
                      (list (cons prop:q 8))))
> (q-ref struct:c)
9
> (p-ref struct:c)
3

변경 사항: base 패키지 7.0 버전에서, Racket의 CS 구현이 가드 프로시저에 제공되는 정보에서 조상 구조체 타입(있으면)을 노출하는 검사자를 건너뛰도록 바뀌었어요. 8.4.0.2 버전에서 accessor-name, contract-str, realm 인자가 추가됐어요. 8.5.0.2 버전에서 Racket의 BC 구현도 가드 프로시저에 제공되는 조상 정보에 대해 CS 구현과 동일하게 검사자를 건너뛰도록 바뀌었어요.

(struct-type-property? v) → boolean?
  v : any/c

v가 구조체 타입 속성 기술자 값이면 #t, 아니면 #f를 반환해요.

(struct-type-property-accessor-procedure? v) → boolean?
  v : any/c

vmake-struct-type-property가 만들어낸 접근자 프로시저이면 #t, 아니면 #f를 반환해요.

(struct-type-property-predicate-procedure? v [prop]) → boolean?
  v : any/c
  prop : (or/c struct-type-property? #f) = #f

vmake-struct-type-property가 만들어낸 술어 프로시저이고, prop#f이거나 make-struct-type-property에 대한 같은 호출로 만들어졌다면 #t, 아니면 #f를 반환해요.

base 패키지 7.5.0.11 버전에서 추가.

더 알아보기

  • 제네릭 인터페이스(Generic Interfaces): 구조체 타입 속성 위의 고수준 API
  • 5.2 구조체 타입 만들기: make-struct-type#:property
  • The Racket Guide의 프로그래머가 정의하는 데이터 타입 장