구조체 타입 만들기
구조체 타입 만들기
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 = #fprops: (listof (cons/c struct-type-property? any/c)) = nullinspector: (or/c inspector? #f 'current 'prefab) = 'currentproc-spec: (or/c procedure? exact-nonnegative-integer? #f) = #fimmutables: (listof exact-nonnegative-integer?) = nullguard: (or/c procedure? #f) = #fconstructor-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이 정수일 때 immutables에 proc-spec을 포함하는 것과도 같아요.
immutables 인자는 필드 위치들의 리스트를 제공해요. 리스트의 각 요소는 고유해야 하며, 그렇지 않으면 exn:fail:contract 예외가 발생해요. 각 요소는 0(포함)부터 init-field-cnt(제외) 범위에 있어야 하며, 그렇지 않으면 exn:fail:contract 예외가 발생해요.
guard 인자는 n+1개 인자를 받는 프로시저 또는 #f예요. 여기서 n은 새 구조체 타입 생성자의 인자 수(init-field-cnt에 super-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) = #fcan-impersonate: any/c = #f
id로 이름붙은 구조체 타입 속성 디스크립터를 만들어요. guard와 can-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로 참조하거나, 속성 접근자가 만들어낸 프로시저를 사용해요.