CHECK-TYPE 매크로
CHECK-TYPE 매크로 (check-type)
check-type은 place가 원하는 타입인지 확인하고, 아니면 정정 가능한 오류를 내는 매크로예요. assert가 임의의 조건을 검사한다면, check-type은 '값의 타입' 검사에 특화된 도구예요. 함수 인자로 들어온 값이 기대 타입인지를 런타임에 강제할 때 아주 자주 쓰여요.
문법 (Syntax)
check-type place typespec [string] => nil
인자와 값 (Arguments and Values)
place— 장소(place)예요.typespec— 타입 지정자(type specifier)예요.string— 문자열이며, 평가돼요.
설명 (Description)
check-type은 place의 내용물이 타입 typespec이 아니면 type-error 타입의 정정 가능한 오류를 신호해요.
check-type은 store-value restart가 호출될 때만 돌아올 수 있어요. (핸들러에서 명시적으로, 또는 디버거가 제시하는 옵션 중 하나로 암시적으로.) store-value restart가 호출되면, check-type은 restart 호출의 인자(또는 디버거가 대화형으로 물어본 값)인 새 값을 place에 저장하고, 다시 시작하며 새 값의 타입을 확인하고 여전히 원하는 타입이 아니면 또 오류를 신호해요.
place가 처음 평가될 때는 일반 평가 규칙으로 평가돼요. 타입 검사가 실패하고 store-value restart를 쓰면 나중에 place로 평가돼요 (Section 5.1.1.1 참고).
string은 타입에 대한 영문 설명이어야 하고, 부정관사("a" 또는 "an")로 시작해야 해요. string이 주어지지 않으면 typespec으로부터 자동 계산돼요. 자동 생성된 메시지는 place·그 내용물·원하는 타입을 언급해요. 어떤 구현은 place가 특정 형태(예: check-type을 호출한 함수의 인자 중 하나)임을 알아차리면 조금 다르게 표현된 오류 메시지를 만들기도 해요. 일부 응용에서는 typespec으로 자동 생성하는 것보다 더 구체적인 설명이 필요할 수 있어서 string을 허용해요.
예제 (Examples)
(setq aardvarks '(sam harry fred))
=> (SAM HARRY FRED)
(check-type aardvarks (array * (3)))
>> Error: The value of AARDVARKS, (SAM HARRY FRED),
>> is not a 3-long array.
>> To continue, type :CONTINUE followed by an option number:
>> 1: Specify a value to use instead.
>> 2: Return to Lisp Toplevel.
>> Debug> :CONTINUE 1
>> Use Value: #(SAM FRED HARRY)
=> NIL
aardvarks
=> #<ARRAY-T-3 13571>
(map 'list #'identity aardvarks)
=> (SAM FRED HARRY)
(setq aardvark-count 'foo)
=> FOO
(check-type aardvark-count (integer 0 *) "A positive integer")
>> Error: The value of AARDVARK-COUNT, FOO, is not a positive integer.
>> To continue, type :CONTINUE followed by an option number:
>> 1: Specify a value to use instead.
>> 2: Top level.
>> Debug> :CONTINUE 2
두 번째 호출에서 string으로 "A positive integer"를 준 예제를 보면, 사용자 지정 문자열이 오류 메시지에 그대로 쓰이는 걸 확인할 수 있어요.
(defmacro define-adder (name amount)
(check-type name (and symbol (not null)) "a name for an adder function")
(check-type amount integer)
`(defun ,name (x) (+ x ,amount)))
(macroexpand '(define-adder add3 3))
=> (defun add3 (x) (+ x 3))
(macroexpand '(define-adder 7 7))
>> Error: The value of NAME, 7, is not a name for an adder function.
>> To continue, type :CONTINUE followed by an option number:
>> 1: Specify a value to use instead.
>> 2: Top level.
>> Debug> :Continue 1
>> Specify a value to use instead.
>> Type a form to be evaluated and used instead: 'ADD7
=> (defun add7 (x) (+ x 7))
매크로 정의 시점에 인자의 타입을 검사하는 용법이에요. name이 잘못된 값 7이면 오류를 내고, 사용자가 'ADD7을 제공하면 매크로가 제대로 확장돼요.
부수 효과 (Side Effects)
디버거에 들어갈 수 있어요.
영향 (Affected By)
*break-on-signals*- 구현(implementation).
예외 상황 (Exceptional Situations)
없음.
함께 보기 (See Also)
- Section 9.1 (Condition System Concepts)
참고 (Notes)
다음은 check-type을 assert로 표현한 동치식이에요.
(check-type place typespec)
== (assert (typep place 'typespec) (place)
'type-error :datum place :expected-type 'typespec)