구조체 타입 만들기

구조체 타입 만들기

make-struct-type를 비롯한 저수준 내장 함수들은 struct의 편의 없이 구조체 타입을 바닥부터 만들 수 있게 해줘요. 이런 함수들은 구조체 타입, 접근자, 변경자, 술어 등을 생성하는 데 필요한 핵심 요소예요.

이 절에서는 구조체 타입을 만드는 저수준 함수들과 구조체 타입 속성, 그리고 생성된 접근자·변경자를 만드는 함수들을 다뤄요.

출처: Racket Reference

본문

procedure

(make-struct-type name super-type init-field-cnt auto-field-cnt
                 [auto-v props inspector proc-spec immutables
                  guard constructor-name])
  → struct-type?
    struct-constructor-procedure?
    struct-predicate-procedure?
    struct-accessor-procedure?
    struct-mutator-procedure?
  • name : symbol?
  • super-type : (or/c struct-type? #f)
  • init-field-cnt : exact-nonnegative-integer?
  • auto-field-cnt : exact-nonnegative-integer?
  • auto-v : any/c = #f
  • props : (listof (cons/c struct-type-property? any/c)) = null
  • inspector : (or/c inspector? #f 'current 'prefab) = 'current
  • proc-spec : (or/c procedure? exact-nonnegative-integer? #f) = #f
  • immutables : (listof exact-nonnegative-integer?) = null
  • guard : (or/c procedure? #f) = #f
  • constructor-name : (or/c symbol? #f) = #f

inspector'prefab이 아니면 새 구조체 타입을 만들고, 'prefab이면 make-struct-type이 prefab 구조체 타입에 접근해요.

name 인자는 타입 이름으로 사용돼요. super-type#f가 아니면 결과 타입은 해당 구조체 타입의 하위 타입이 돼요.

결과 구조체 타입은 init-field-cnt+auto-field-cnt개의 필드를 가져요(super-type의 필드에 더해), 하지만 생성자 인자는 init-field-cnt개만 가져요(super-type의 생성자 인자에 더해). 나머지 필드는 auto-v로 초기화돼요. 총 필드 수(super-type 필드 포함)는 32768을 넘을 수 없어요.

props 인자는 쌍들의 리스트로, 각 쌍의 car는 구조체 타입 속성 디스크립터이고 cdr은 임의의 값이에요. 속성은 props 안에서 여러 번 명시될 수 있지만(props에 직접 포함된 속성들이 자동으로 추가하는 속성들 포함), 연관된 값들이 eq?인 경우에만 가능하고, 그렇지 않으면 exn:fail:contract 예외가 발생해요. 속성에 대한 자세한 내용은 「Structure Type Properties」를 참고해요. inspector'prefab이면 props는 반드시 null이어야 해요.

inspector 인자는 보통 구조체 타입과 그 인스턴스에 대한 반영(reflective) 정보 접근을 제어해요. 「Structure Inspectors」를 참고해요. inspector'prefab이면 결과 prefab 구조체 타입과 그 인스턴스는 항상 투명해요. inspector#f이면 구조체 타입의 인스턴스들이 투명해져요. inspector'current(기본값)이면 (current-inspector)가 사용돼요.

proc-spec이 정수나 프로시저이면, 구조체 타입의 인스턴스들이 프로시저로 동작해요. 자세한 내용은 prop:procedure를 참고해요. proc-spec#f가 아닌 값을 제공하는 것은, 그 값을 props의 끝에 prop:procedure와 짝지어 넣는 것과 같고, proc-spec이 정수일 때 immutablesproc-spec을 포함하는 것과도 같아요.

immutables 인자는 필드 위치들의 리스트를 제공해요. 리스트의 각 요소는 고유해야 하며, 그렇지 않으면 exn:fail:contract 예외가 발생해요. 각 요소는 0(포함)부터 init-field-cnt(제외) 범위에 있어야 하며, 그렇지 않으면 exn:fail:contract 예외가 발생해요.

guard 인자는 n+1개 인자를 받는 프로시저 또는 #f예요. 여기서 n은 새 구조체 타입 생성자의 인자 수(init-field-cntsuper-type이 암시하는 생성자 인자 수를 더한 값)예요. guard가 프로시저면, 그 타입의 인스턴스가 생성될 때마다, 또는 하위 타입의 인스턴스가 생성될 때마다 그 프로시저가 호출돼요. guard의 인자는 구조체의 처음 n개 필드에 제공된 값들 뒤에, 인스턴스화되는 구조체 타입의 이름이 따라오는 형태예요.

...

procedure

(make-struct-field-accessor make-struct-type field-idx)
  → (struct-accessor-procedure? . -> . any/c)

make-struct-type이 돌려준 구조체 타입을 받아, 필드 인덱스 field-idx를 추출하는 접근자 프로시저를 만들어요.

procedure

(make-struct-field-mutator make-struct-type field-idx)
  → (struct-mutator-procedure? . -> . void?)

make-struct-type이 돌려준 구조체 타입을 받아, 필드 인덱스 field-idx를 변경하는 변경자 프로시저를 만들어요.

procedure

(make-struct-type-property id [guard] [can-impersonate])
  → struct-type-property?
  • id : symbol?
  • guard : (structural-property-guard? . -> . any/c) = #f
  • can-impersonate : any/c = #f

id로 이름붙은 구조체 타입 속성 디스크립터를 만들어요. guardcan-impersonate에 대한 자세한 내용은 「Structure Type Properties」를 참고해요.

(make-struct-type-property id)
(make-struct-type-property id guard)
(make-struct-type-property id guard can-impersonate)

procedure

(struct-type-property? v) → boolean?

v가 구조체 타입 속성 디스크립터이면 #t를 돌려줘요.

(struct-type-property? v)

procedure

(struct-type-property-accessor (make-struct-type-property ...) . -> . procedure?)

속성 디스크립터를 받아, 구조체 인스턴스에서 속성 값을 추출하는 접근자 프로시저를 만들어요.

(struct-type-property-accessor property-id)

속성 값이 일반 값으로 사용되려면 struct-type-property-ref로 참조하거나, 속성 접근자가 만들어낸 프로시저를 사용해요.

더 알아보기