SETF, PSETF — place에 값을 저장하는 매크로

SETF, PSETF — place에 값을 저장하는 매크로

Lisp에서 값을 '넣는다'고 하면 가장 먼저 떠올리는 게 setf예요. 단순 변수뿐 아니라 접근자(accessor)로 읽을 수 있는 어떤 장소(place)든 값을 바꿔 넣을 수 있게 해주는 범용 갱신 매크로예요. psetf는 여러 장소를 병렬로 갱신할 때 쓰는 형제 매크로예요.

출처: CLHS: Macro SETF, PSETF

시그니처

setf {pair}* => results*
psetf {pair}* => nil
pair::= place newvalue

본문

인자와 값 (Arguments and Values)

  • place — place.
  • newvalue — 폼(form).
  • results — 마지막 place의 저장 폼이 돌려준 다중 값(multiple values), pair가 없으면 nil.

설명 (Description)

setfplace의 값을 newvalue로 바꿔요.

(setf place newvalue)newvalue를 평가한 결과를 place가 가리키는 위치에 저장하는 갱신 폼으로 확장돼요. 어떤 place 폼들은 선택적 인자를 받는 접근자를 쓰기도 해요. 그런 선택적 인자들이 setf에서 허용되는지, 어떻게 쓰이는지는 setf 확장 함수에게 달렸고 setf가 통제하지 않아요. &optional, &rest, &key 인자를 받으면서 setf와 함께 쓸 수 있다고 주장하는 함수의 문서는 그 인자들이 어떻게 다뤄지는지 반드시 명시해야 해요.

pair가 여러 개 주어지면 순차적으로 처리돼요. 즉,

 (setf place-1 newvalue-1
       place-2 newvalue-2
       ...
       place-N newvalue-N)

는 정확히 이와 동등해요:

 (progn (setf place-1 newvalue-1)
        (setf place-2 newvalue-2)
        ...
        (setf place-N newvalue-N))

psetfpair가 여러 개면 새 값들을 장소들에 병렬로 할당해요. 좀 더 정확히는, 평가할 모든 하위 폼(place와 newvalue 폼 양쪽)을 왼쪽에서 오른쪽으로 다 평가한 뒤, 모든 할당을 예측 불가능한 순서로 수행해요.

setfpsetf 확장의 자세한 처리는 Section 5.1.2 (Kinds of Places)를 보세요.

예제 (Examples)

 (setq x (cons 'a 'b) y (list 1 2 3)) =>  (1 2 3)
 (setf (car x) 'x (cadr y) (car x) (cdr x) y) =>  (1 X 3)
 x =>  (X 1 X 3)
 y =>  (1 X 3)
 (setq x (cons 'a 'b) y (list 1 2 3)) =>  (1 2 3)
 (psetf (car x) 'x (cadr y) (car x) (cdr x) y) =>  NIL
 x =>  (X 1 A 3)
 y =>  (1 A 3)

예제에서 psetf는 새 값들을 모두 평가한 뒤 병렬로 넣기 때문에, (car x)에는 'x가, (cadr y)에는 원래 xcar였던 a가 들어가는 걸 확인할 수 있어요.

영향 (Affected By)

define-setf-expander, defsetf, *macroexpand-hook*.

특이 상황 (Exceptional Situations)

없음.

참고 (Notes)

없음.

더 알아보기

  • define-setf-expander, defsetf — place 확장자 정의
  • rotatef, shiftf — 값들을 회전·이동시키는 매크로
  • macroexpand-1 — 매크로 확장 확인