ASSERT 매크로

ASSERT 매크로 (assert)

assert검증(assertion) 조건이 참인지 확인하고, 거짓이면 정정 가능한(correctable) 오류를 일으키는 매크로예요. 디버깅이나 방어적 프로그래밍에서 전제 조건을 강제할 때 쓰는데, 단순히 오류를 내는 데서 끝나는 게 아니라 사용자가 관련 place 값을 고쳐서 다시 시도할 수 있게 해주는 데 특징이 있어요.

출처: CLHS: Macro ASSERT

문법 (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)

asserttest-form이 참으로 평가되도록 보장해요. test-form이 거짓으로 평가되면 assert는 (datumarguments로 나타내는) 정정 가능한 오류를 신호해요. continue restart를 써서 오류에서 계속하면, 사용자가 place들의 값을 바꾼 뒤 asserttest-form을 다시 평가하게 할 수 있어요. test-form의 값이 참(non-nil)이면 assertnil을 돌려줘요.

placetest-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 명령을 주면 참조들 중 아무 값이나 바꿀 수 있어요. 이 상세 동작은 구현의 사용자 인터페이스 스타일에 따라 달라요.

더 알아보기 (Learn more)