ASSERT 매크로
ASSERT 매크로 (assert)
assert는 검증(assertion) 조건이 참인지 확인하고, 거짓이면 정정 가능한(correctable) 오류를 일으키는 매크로예요. 디버깅이나 방어적 프로그래밍에서 전제 조건을 강제할 때 쓰는데, 단순히 오류를 내는 데서 끝나는 게 아니라 사용자가 관련 place 값을 고쳐서 다시 시도할 수 있게 해주는 데 특징이 있어요.
문법 (Syntax)
assert test-form [(place*) [datum-form argument-form*]]
=> nil
인자와 값 (Arguments and Values)
test-form— 폼이며, 항상 평가돼요.place— 장소(place)이며, 오류가 나면 평가돼요.datum-form— 데이터(datum)로 평가되는 폼이에요. 오류가 나야 할 때마다 평가되거나, 오류가 나지 않을 때는 전혀 평가되지 않아요.argument-form— 인자(argument)로 평가되는 폼이에요. 오류가 나야 할 때마다 평가되거나, 오류가 나지 않을 때는 전혀 평가되지 않아요.datum,arguments— 기본 타입이 error인 조건(condition)의 지정자(designator)예요. (datum-form과 각argument-form의 평가 결과예요.)
설명 (Description)
assert는 test-form이 참으로 평가되도록 보장해요. test-form이 거짓으로 평가되면 assert는 (datum과 arguments로 나타내는) 정정 가능한 오류를 신호해요. continue restart를 써서 오류에서 계속하면, 사용자가 place들의 값을 바꾼 뒤 assert가 test-form을 다시 평가하게 할 수 있어요. test-form의 값이 참(non-nil)이면 assert는 nil을 돌려줘요.
place는 test-form이 의존하는 데이터에 대한 **일반화된 참조(generalized reference)**예요. 사용자가 오류를 고치려고 시도할 때 값을 바꿀 수 있는 대상이에요. 각 place의 하위 폼은 오류가 신호될 때만 평가되고, (문제를 실제로 고치지 않고 계속했을 때) 오류가 다시 신호되면 다시 평가될 수 있어요. place의 평가 순서는 지정되지 않아요 (Section 5.1.1.1 참고). place 폼이 저장 변수보다 많은 값을 만들면 넘치는 값은 무시되고, 저장 변수보다 적은 값을 만들면 빠진 값은 nil로 설정돼요.
예제 (Examples)
(setq x (make-array '(3 5) :initial-element 3))
=> #2A((3 3 3 3 3) (3 3 3 3 3) (3 3 3 3 3))
(setq y (make-array '(3 5) :initial-element 7))
=> #2A((7 7 7 7 7) (7 7 7 7 7) (7 7 7 7 7))
(defun matrix-multiply (a b)
(let ((*print-array* nil))
(assert (and (= (array-rank a) (array-rank b) 2)
(= (array-dimension a 1) (array-dimension b 0)))
(a b)
"Cannot multiply ~S by ~S." a b)
(really-matrix-multiply a b))) => MATRIX-MULTIPLY
(matrix-multiply x y)
>> Correctable error in MATRIX-MULTIPLY:
>> Cannot multiply #<ARRAY ...> by #<ARRAY ...>.
>> Restart options:
>> 1: You will be prompted for one or more new values.
>> 2: Top level.
>> Debug> :continue 1
>> Value for A: x
>> Value for B: (make-array '(5 3) :initial-element 6)
=> #2A((54 54 54 54 54)
(54 54 54 54 54)
(54 54 54 54 54)
(54 54 54 54 54)
(54 54 54 54 54))
행렬 곱셈 예시에서 볼 수 있듯, assert의 두 번째 인자 (a b)는 "문제가 있으면 이 값들을 고치게 할 수 있는 대상"이라는 뜻이에요. 사용자가 B를 올바른 차원의 행렬로 :continue로 바꾸자 같은 assert가 통과하고 실제 계산이 이뤄져요.
(defun double-safely (x) (assert (numberp x) (x)) (+ x x))
(double-safely 4)
=> 8
(double-safely t)
>> Correctable error in DOUBLE-SAFELY: The value of (NUMBERP X) must be non-NIL.
>> Restart options:
>> 1: You will be prompted for one or more new values.
>> 2: Top level.
>> Debug> :continue 1
>> Value for X: 7
=> 14
영향 (Affected By)
*break-on-signals*- 활성화된 조건 핸들러(condition handler)들의 집합.
예외 상황 (Exceptional Situations)
없음.
함께 보기 (See Also)
check-type,error, Section 5.1 (Generalized Reference)
참고 (Notes)
디버거는 오류 메시지에 test-form을 포함할 필요가 없고, place는 메시지에 넣으면 안 되지만 사용자가 볼 수 있게는 제공해야 해요. 사용자가 continue 명령을 주면 참조들 중 아무 값이나 바꿀 수 있어요. 이 상세 동작은 구현의 사용자 인터페이스 스타일에 따라 달라요.