SYMBOL-MACROLET 특수 연산자

SYMBOL-MACROLET 특수 연산자 (symbol-macrolet)

symbol-macrolet심볼을 매크로 확장 대상으로 만들어 버리는 특수 연산자예요. 심볼 매크로(symbol macro)를 렉시컬로 등록해서, 해당 심볼이 변수처럼 쓰이는 자리를 코드 작성 시점에 다른 폼으로 치환되게 해줘요. 변수처럼 보이지만 실제로는 특정 표현식으로 매번 펼쳐지는 '가짜 변수'를 만들 때 씁니다.

출처: CLHS: Special Operator SYMBOL-MACROLET

문법 (Syntax)

symbol-macrolet ((symbol expansion)*) declaration* form*
=> result*

인자와 값 (Arguments and Values)

  • symbol — 심볼이에요.
  • expansion — 폼이에요.
  • declarationdeclare 표현식이며, 평가되지 않아요.
  • forms — 암시적 progn(implicit progn)이에요.
  • resultsforms가 돌려주는 값들이에요.

설명 (Description)

symbol-macrolet은 심볼의 매크로 확장 환경에 영향을 주는 메커니즘을 제공해요.

symbol들이 이름 붙인 각 심볼 매크로에 대해, 렉시컬로 확장 함수가 등록돼요. 심볼 매크로의 확장 함수가 보장하는 유일한 성질은, 그 함수를 폼과 환경에 적용했을 때 올바른 확장을 돌려준다는 것이에요. (확장이 함수·환경·둘 다 중 어디에 저장되는지는 구현에 따라 달라요.)

symbol-macrolet의 렉시컬 스코프 안에서 symbol을 변수처럼 참조하는 모든 자리(예: setq)는 일반 매크로 확장 과정을 거쳐 펼쳐져요. 심볼 매크로의 확장은 심볼 매크로 호출과 같은 렉시컬 환경에서, 일반 매크로와 똑같이 추가 확장될 수 있어요.

let에서 허용되는 것과 **동일한 선언(declaration)**이 허용되는데, 예외가 하나 있어요. symbol-macrolet이 정의하는 심볼 중 하나를 special 선언이 가리키면 오류가 나요.

symbol-macroletforms가 확장될 때, 지정된 변수 중 하나의 값을 설정하는 setqsetf처럼 취급돼요. 심볼 매크로로 정의된 심볼의 psetqpsetf처럼, multiple-value-setqvaluessetf처럼 취급돼요.

symbol-macroletlet에 의해 가려질 수 있어요. 다시 말해 symbol-macrolet은, 그 forms를 감싸는 어떤 렉시컬 바인딩의 scope 안에 있는 심볼의 등장만 대체해요.

예제 (Examples)

;;; The following is equivalent to
;;;   (list 'foo (let ((x 'bar)) x)),
;;; not
;;;   (list 'foo (let (('foo 'bar)) 'foo))
(symbol-macrolet ((x 'foo))
  (list x (let ((x 'bar)) x))) 
=>  (foo bar)
NOT=>  (foo foo) 

(symbol-macrolet ((x '(foo x)))
  (list x))
=>  ((FOO X))

첫 예제가 let에 의한 shadowing을 보여줘요. 바깥의 symbol-macroletx'foo로 확장하지만, 안쪽 let이 만든 렉시컬 x 바인딩은 이를 가려서 실제 변수로 동작해요. 그래서 결과가 (foo foo)가 아니라 (foo bar)가 됩니다.

영향 (Affected By)

없음.

예외 상황 (Exceptional Situations)

  • 전역 변수(global variable)로 정의된 심볼을 바인딩하려 하면 program-error 타입 오류가 나요.
  • declarationsymbol-macrolet이 바인딩하는 심볼 중 하나를 특수(special)로 선언하면 program-error 타입 오류가 나요.

함께 보기 (See Also)

  • with-slots, macroexpand

참고 (Notes)

symbol-macrolet 특수 폼은 with-slots를 구현할 때 쓰는 기본 메커니즘이에요.

symbol-macrolet 폼이 최상위 폼(top level form)이면, 그 forms도 최상위 폼으로 처리돼요. Section 3.2.3 (File Compilation) 참고.

더 알아보기 (Learn more)