DEFUN — 함수 정의하기
DEFUN — 함수 정의하기 (매크로)
이름 붙은 전역 function을 정의하는 가장 기본적인 함수 정의 매크로예요. 본문을 implicit progn으로 실행하고, 암묵적으로 이름 붙은 block으로 감싸서 return-from으로 조기 복귀할 수 있어요. Common Lisp 코드의 대부분이 이 매크로로 만들어져요.
시그니처 (Syntax)
defun function-name lambda-list [[declaration* | documentation]] form* => function-name
function-name— function name.lambda-list— ordinary lambda list.declaration— declare expression. 평가되지 않아요.documentation—string. 평가되지 않아요.forms— implicit progn.block-name—function-name의 function block name.
본문 (Description)
defun은 global environment에 function-name이라는 새 function을 정의해요. defun이 정의한 function의 본문은 forms로 이루어져 있고, 그 function이 호출되면 implicit progn으로 실행돼요. defun은 새 function을 정의하거나, 잘못된 정의의 수정본을 설치하거나, 이미 정의된 function을 재정의하거나, macro를 function으로 재정의하는 데 쓸 수 있어요.
defun은 정의되는 function의 본문 forms(lambda-list의 forms는 아님)를 block-name이라는 block으로 암묵적으로 감싸요.
Documentation은 name에 function 종류로, 그리고 function object에도 documentation string으로 붙어요.
defun을 평가하면 function-name이 lexical environment에서 처리된 다음 lambda expression이 지정하는 function의 전역 이름이 돼요:
(lambda lambda-list
[[declaration* | documentation]]
(block block-name form*))
(lambda expression은 macro expansion 시점에 어떤 인자도 평가되지 않아요.)
defun은 컴파일 타임 부수효과를 수행할 의무가 없어요. 특히 defun은 컴파일 시점에 function 정의를 사용 가능하게 만들지 않아요. implementation은 컴파일 타임 에러 검사(호출의 인자 수 검사 같은 것)를 위해 function에 대한 정보를 저장하거나, function이 inline으로 확장되게 할 수 있어요.
예제 (Examples)
(defun recur (x)
(when (> x 0)
(recur (1- x)))) => RECUR
(defun ex (a b &optional c (d 66) &rest keys &key test (start 0))
(list a b c d keys test start)) => EX
(ex 1 2) => (1 2 NIL 66 NIL NIL 0)
(ex 1 2 3 4 :test 'equal :start 50)
=> (1 2 3 4 (:TEST EQUAL :START 50) EQUAL 50)
(ex :test 1 :start 2) => (:TEST 1 :START 2 NIL NIL 0)
;; This function assumes its callers have checked the types of the
;; arguments, and authorizes the compiler to build in that assumption.
(defun discriminant (a b c)
(declare (number a b c))
"Compute the discriminant for a quadratic equation."
(- (* b b) (* 4 a c))) => DISCRIMINANT
(discriminant 1 2/3 -2) => 76/9
;; This function assumes its callers have not checked the types of the
;; arguments, and performs explicit type checks before making any assumptions.
(defun careful-discriminant (a b c)
"Compute the discriminant for a quadratic equation."
(check-type a number)
(check-type b number)
(check-type c number)
(locally (declare (number a b c))
(- (* b b) (* 4 a c)))) => CAREFUL-DISCRIMINANT
(careful-discriminant 1 2/3 -2) => 76/9
더 알아보기 (See Also)
flet, labels, block, return-from, declare, documentation, Section 3.1 (Evaluation), Section 3.4.1 (Ordinary Lambda Lists), Section 3.4.11 (Syntactic Interaction of Documentation Strings and Declarations)
Notes
return-from을 쓰면 defun이 정의한 function에서 일찍 복귀할 수 있어요.
(보통 디버깅 정보인) 추가 정보가 함수 정의에 기록될 때 추가 부수효과가 일어날 수 있어요.