WITH-ACCESSORS — CLOS 슬롯을 지역 변수처럼 쓰는 매크로
WITH-ACCESSORS — CLOS 슬롯을 지역 변수처럼 쓰는 매크로
CLOS 객체의 슬롯을 접근자(accessor)를 통해 읽고 쓰는 일을 반복하다 보면 코드가 길어지기 쉬워요. with-accessors는 슬롯을 지역 변수처럼 이름으로 접근할 수 있게 해서 그 반복을 줄여줘요.
이 문서는 CLOS(객체지향) 관련 매크로입니다. 슬롯 접근을 편하게 하는 데 주로 유용해요.
시그니처
with-accessors ({slot-entry}*) instance-form declaration* form* => results*
slot-entry::= (variable-name accessor-name)
본문
인자와 값 (Arguments and Values)
variable-name— 변수 이름(variable name); 평가되지 않아요.accessor-name— 함수 이름(function name); 평가되지 않아요.instance-form— 폼; 평가돼요.declaration—declare식; 평가되지 않아요.forms— 암묵적 progn.results—forms가 돌려준 값.
설명 (Description)
slot-entry로 지정된 슬롯들을 마치 변수인 것처럼 접근자를 통해 어휘적으로 쓸 수 있는 어휘 환경을 만들어요. with-accessors는 slot-entry로 지정된 슬롯에 접근하기 위해 적절한 접근자들을 호출해요. setf와 setq 둘 다 슬롯 값을 설정하는 데 쓸 수 있어요.
예제 (Examples)
(defclass thing ()
((x :initarg :x :accessor thing-x)
(y :initarg :y :accessor thing-y)))
=> #<STANDARD-CLASS THING 250020173>
(defmethod (setf thing-x) :before (new-x (thing thing))
(format t "~&Changing X from ~D to ~D in ~S.~%"
(thing-x thing) new-x thing))
(setq thing1 (make-instance 'thing :x 1 :y 2)) => #<THING 43135676>
(setq thing2 (make-instance 'thing :x 7 :y 8)) => #<THING 43147374>
(with-accessors ((x1 thing-x) (y1 thing-y))
thing1
(with-accessors ((x2 thing-x) (y2 thing-y))
thing2
(list (list x1 (thing-x thing1) y1 (thing-y thing1)
x2 (thing-x thing2) y2 (thing-y thing2))
(setq x1 (+ y1 x2))
(list x1 (thing-x thing1) y1 (thing-y thing1)
x2 (thing-x thing2) y2 (thing-y thing2))
(setf (thing-x thing2) (list x1))
(list x1 (thing-x thing1) y1 (thing-y thing1)
x2 (thing-x thing2) y2 (thing-y thing2)))))
>> Changing X from 1 to 9 in #<THING 43135676>.
>> Changing X from 7 to (9) in #<THING 43147374>.
=> ((1 1 2 2 7 7 8 8)
9
(9 9 2 2 7 7 8 8)
(9)
(9 9 2 2 (9) (9) 8 8))
예제에서 x1, y1처럼 보이는 이름이 실제로는 thing-x, thing-y 접근자를 통해 슬롯을 읽고 쓰는 걸 확인할 수 있어요.
영향 (Affected By)
defclass.
특이 상황 (Exceptional Situations)
어떤 accessor-name이 그 인스턴스의 접근자 이름이 아니면 결과는 정의되지 않아요(undefined).
참고 (Notes)
다음 형태의 with-accessors 식은:
(with-accessors (slot-entry1 ... slot-entryn) instance-form form1 ... formk)
이것과 동등하게 확장돼요:
(let ((in instance-form))
(symbol-macrolet (Q1 ... Qn) form1 ... formk))
여기서 Qi는 이래요:
(variable-namei () (accessor-namei in))
더 알아보기
with-slots— 슬롯을 직접 이름으로 접근하는 매크로symbol-macrolet— 심볼 매크로 설치 매크로