TAGBODY 특수 연산자

TAGBODY 특수 연산자 (tagbody)

tagbody는 Common Lisp에서 레이블(tag) 기반의 점프 제어 구조를 만들어 주는 특수 연산자예요. 마치 어셈블리의 레이블과 goto처럼, 본문 중간에 태그를 찍어 두고 go로 그 지점으로 뛰어가는 식으로 동작해요. block·return-from이 '블록에서 빠져나가기'에 특화됐다면, tagbody는 '본문 안에서 앞뒤로 자유롭게 이동'하는 데 초점이 맞춰져 있어요.

출처: CLHS: Special Operator TAGBODY

문법 (Syntax)

tagbody {tag | statement}* => nil

인자와 값 (Arguments and Values)

  • tag — go 태그(go tag)이며, 평가되지 않아요.
  • statement — 복합 폼(compound form)이며, 아래 설명대로 평가돼요.

설명 (Description)

tagbody는 태그로 표시된 레이블로의 제어 이동을 제공하는 렉시컬 환경 안에서, 0개 이상의 statement를 실행해요.

tagbodystatement들은 왼쪽에서 오른쪽 순서대로 평가되고, 그 값은 버려져요. 남은 statement가 없으면 tagbodynil을 돌려줍니다. 그런데 (go tag)가 평가되면, 제어는 그 태그가 붙은 본문 부분으로 점프해요. (태그 비교는 eql로 해요.)

tagbody가 만든 태그는 렉시컬 스코프와 **다이내믹 익스텐트(dynamic extent)**를 가져요. 일단 tagbody를 빠져나가면, 그 안의 태그로 go 하는 것은 더 이상 유효하지 않아요. go가 자기 자신을 포함하는 가장 안쪽 tagbody가 아닌 다른 tagbody로 점프하는 것도 허용돼요. tagbody가 만든 태그는 같은 이름의 다른 태그를 가릴(그림자) 뿐이에요.

본문의 어떤 요소가 tag이고 어떤 것이 statement인지는, 해당 요소의 매크로 확장 이전에 결정돼요. statement가 매크로 폼인데 그 확장 결과가 원자(atom)라면, 그 원자는 태그가 아니라 statement로 취급돼요.

예제 (Examples)

(let (val)
  (tagbody
    (setq val 1)
    (go point-a)
    (incf val 16)
   point-c
    (incf val 04)
    (go point-b)
    (incf val 32)
   point-a
    (incf val 02)
    (go point-c)
    (incf val 64)
   point-b
    (incf val 08))
  val)
=>  15
(defun f1 (flag)
  (let ((n 1))
    (tagbody 
      (setq n (f2 flag #'(lambda () (go out))))
     out
      (prin1 n))))
=>  F1
(defun f2 (flag escape)
  (if flag (funcall escape) 2))
=>  F2
(f1 nil)
>>  2
=>  NIL
(f1 t)
>>  1
=>  NIL

첫 예제에서 go로 태그 사이를 옮겨 다니며 val을 1, +02, +04, +08 순서로 더했더니 15가 나와요. 점프 순서를 따라가 보면 point-a → point-c → point-b로 흐르는 걸 확인할 수 있어요. 두 번째 예제는 보조 함수 안에서 람다로 감싼 (go out)이 바깥 tagbody의 태그로 점프하는, 빠져나가지 않고 안쪽으로 들어가는 다이내믹한 제어 흐름을 보여줘요.

영향 (Affected By)

없음.

예외 상황 (Exceptional Situations)

없음.

함께 보기 (See Also)

  • go

참고 (Notes)

다음 매크로들은 **암시적 태그바디(implicit tagbody)**를 가져요.

do              do-external-symbols  dotimes  
do*             do-symbols           prog     
do-all-symbols  dolist               prog*    

Figure 5-10. Macros that have implicit tagbodies.

더 알아보기 (Learn more)