DEFMETHOD — 제네릭 함수에 메서드 정의하기

DEFMETHOD — 제네릭 함수에 메서드 정의하기 (매크로)

generic functionmethod를 정의하는 매크로예요. 인자 타입(파라미터 특수화자)에 따라 어떤 구현이 선택될지 지정해서, Common Lisp의 다중 디스패치(CLOS)를 구성하는 핵심 도구예요.

출처: DEFMETHOD - Common Lisp HyperSpec

시그니처 (Syntax)

defmethod function-name* {method-qualifier}* specialized-lambda-list [[declaration* | documentation]] form* => new-method

function-name ::= {symbol | (setf symbol)}
method-qualifier ::= non-list

specialized-lambda-list ::= ({var | (var parameter-specializer-name)}*
                            [&optional {var | (var [initform [supplied-p-parameter]])}*]
                            [&rest var]
                            [&key {var | ({var | (keyword var)} [initform [supplied-p-parameter]])}*
                                 [&allow-other-keys]]
                            [&aux {var | (var [initform])}*])

parameter-specializer-name ::= symbol | (eql eql-specializer-form)
  • declarationdeclare expression. 평가되지 않아요.
  • documentationstring. 평가되지 않아요.
  • varvariable name.
  • eql-specializer-formform.
  • Formform.
  • Initformform.
  • Supplied-p-parameter — 변수 이름.
  • new-method — 새 method object.

본문 (Description)

매크로 defmethodgeneric functionmethod를 정의해요.

(fboundp function-name)nil이면, 기본값들로 generic function이 생성돼요. 인자 우선순위 순서(각 인자는 인자 목록에서 오른쪽 인자들보다 더 특수함), generic function 클래스(class standard-generic-function), method 클래스(class standard-method), method combination 타입(표준 method combination 타입)이 기본값이에요. generic functionlambda list는 정의되는 methodlambda list와 일치(congruent)해요. defmethod form이 키워드 인자를 언급하면 generic functionlambda list&key를 언급하되 키워드 인자는 언급하지 않아요. function-nameordinary function·macro·special operator를 가리키면 에러가 신호돼요.

현재 generic functionfunction-name으로 이름 붙어 있다면, methodlambda listgeneric functionlambda list와 일치해야 해요. 이 조건이 성립하지 않으면 에러가 신호돼요. 이 맥락에서의 congruence 정의는 Section 7.6.4 (Congruent Lambda-lists for all Methods of a Generic Function)를 보세요.

method-qualifier 인자는 method combination이 주어진 method를 식별하는 데 쓰는 object예요. method combination 타입은 method qualifier가 될 수 있는 것을 더 제한할 수도 있어요. 표준 method combination 타입은 unqualified method와 (유일한 qualifier가 :before, :after, :around 키워드 중 하나인) method를 허용해요.

specialized-lambda-list 인자는 ordinary lambda list와 비슷하되, 필수 매개변수의 name을 특수화된 파라미터로 바꿀 수 있어요. 특수화된 파라미터는 (var parameter-specializer-name) 형태의 list예요. 필수 매개변수만 특수화할 수 있어요. parameter-specializer-namesymbol이면 class를 이름 짓는 거고, list이면 (eql eql-specializer-form) 형태예요. 파라미터 특수화자 이름 (eql eql-specializer-form)은 해당 인자가 eql-specializer-form의 값인 objecteql일 때만 그 method가 applicable하다는 뜻이에요. eql-specializer-formdefmethod 매크로의 확장이 평가되는 시점에 평가돼요. 주어진 필수 매개변수에 parameter specializer name을 지정하지 않으면 parameter specializerclass t로 기본 설정돼요. 더 자세한 내용은 Section 7.6.2 (Introduction to Methods)를 보세요.

form 인자들은 method body를 지정해요. method의 body는 implicit block 안에 감싸져요. function-namesymbol이면 이 block은 generic function과 같은 name을 가져요. function-name이 (setf symbol) 형태의 list이면 block의 namesymbol이에요.

생성되는 method objectclass는 그 method가 정의되는 generic function의 method class 옵션이 주는 값이에요.

generic function이 이미 정의되는 methodparameter specializer·qualifier가 일치하는 method를 갖고 있다면, defmethod는 기존 method를 지금 정의하는 것으로 교체해요. 이 맥락에서의 agreement 정의는 Section 7.6.3 (Agreement on Parameter Specializers and Qualifiers)를 보세요.

parameter specializer는 Section 7.6.2 (Introduction to Methods)에서 설명한 대로 parameter specializer name에서 파생돼요.

defmethod 매크로의 확장은 각 특수화된 파라미터를 "참조"해요(declare의 설명 안에 있는 ignore 설명 참고). 여기에는 명시적 parameter specializer namet인 파라미터도 포함돼요. 이는 method의 body가 특수화된 파라미터를 참조하지 않아도 컴파일러 경고가 발생하지 않지만, 특수화되지 않은 파라미터를 참조하지 않으면 경고가 발생할 수 있다는 뜻이에요. 이런 이유로 t에 특수화하는 파라미터는 이 맥락에서 특수화되지 않은 파라미터와 완전히 동의어는 아니에요.

method body 앞머리의, method의 lambda variable들에 적용되는 선언은 해당 binding들과 같은 scope를 가진 bound declaration으로 취급돼요.

method body 앞머리의, call-next-method·next-method-p의 함수적 binding에 적용되는 선언은 method body form 안에서 그 함수들을 참조하는 데 적용돼요. call-next-method·next-method-p function name의 바깥 binding과 그런 binding에 연관된 선언은 method body form 안에서 shadowed돼요.

method body 앞머리의 free declarationscope는 method body 전체예요. 여기에는 암묵적 로컬 함수 정의는 포함되지만 lambda variableinitialization form은 제외돼요.

defmethod는 컴파일 타임 부수효과를 수행할 의무가 없어요. 특히 method는 컴파일 중에 호출되도록 설치되지 않아요. implementation은 컴파일 타임 에러 검사를 위해 generic function에 대한 정보를 저장할 수 있어요(호출의 인자 수 검사나, 함수 이름의 정의가 보였다는 기록 같은 것).

documentationmethod objectdocumentation string으로 붙어요.

더 알아보기 (See Also)

defgeneric, documentation, Section 7.6.2 (Introduction to Methods), Section 7.6.4 (Congruent Lambda-lists for all Methods of a Generic Function), Section 7.6.3 (Agreement on Parameter Specializers and Qualifiers), Section 3.4.11 (Syntactic Interaction of Documentation Strings and Declarations)

예외 상황 (Exceptional Situations)

function-nameordinary function·macro·special operator를 가리키면 typeerror인 에러가 신호돼요.

현재 generic functionfunction-name으로 이름 붙어 있다면 methodlambda listgeneric functionlambda list와 일치해야 하며, 그렇지 않으면 typeerror인 에러가 신호돼요.

Notes

없음.