1. 定义新函数
(defun name (parameter*)
"Optional docuemntion string."
body-form*)
如果一个字符串紧跟在形参列表之后,那么安应该是一个用来描述函数用途的文档字符串,当函数定义时,该文档字符串被关联到函数名上,并且以后可以通过DOCUMENTATION函数来获取。
(defun hello-world() (format t "hello, world"))
(defun verbose-sum (x y)
"Sum any two numbers after printing a message."
(format t "Summing ~d and ~d. ~%" x y)
(+ x y))
2. 函数形参列表
当形参列表是一个由变量名所组成的简单列表时,如同在verbose-sum里那样,这些形参被称为必要形参,当函数被调用时,必须为它们的每一个必要形参提供一个实参,每一个形参被绑定到对应的实参上,如果一个函数以过少或过多的实参调用的话,Lisp就会报错。
3. 可选形参
为了定义一个带有可选形参的函数,在必要形参的名字之后放置符号&optional,后接可选形参的名字。
(defun foo (a b &optional c d) (list a b c d))
当函数被调用时,实参被首先绑定于到必要形参上。原属有必要形参被赋值后,如果还有任何实参剩余,它们的值被赋给可选形参,如果实参在所有可选形参被赋值之前用完了,那么其余可选形参将自动被绑定到NIL上。
(foo 1 2) -> (1 2 NIL NIL)
(foo 1 2 3) -> (1 2 3 NIL)
(defun foo (a &optional (b 10)) (list a b))
上述函数要求将一个实参绑定到形参a上。当存在第二个实参时,第二个形参b将使用其值,否则使用10
(foo 1 2) -> (1 2)
(foo 1) -> (1 10)
有时需要了解一个可选形参是被调用者赋值还是使用了默认值,可以通过一个变量来做到这一点,这种变量名与对应的真实形参相同,但是带有一个 -supplied-p 后缀。
(defun foo (a b &optional (c 3 c-supplied-p))
(list a b c c-supplied-p))
(foo 1 2) -> (1 2 3 NIL)
(foo 1 2 3) -> (1 2 3 T)
4. 剩余形参 (可变形参)
lisp 允许在符号 &rest 之后包括一揽子形参。如果函数带有 &rest ,那么任何满足了必要和可选形参之后其余所有的实参就将被收集到一个列表里成为该 &rest 形参的值。
FORMAT 和 + 的形参列表可能看起来会是这样
(defun format (stream string &rest values) ...)
(defun + (&rest numbers) ...)
5. 关键字形参
假设有一个接受四个可选形参的函数,如果调用者只想为四个参数中的一个提供值。
(defun foo (&key a b c) (list a b c))
当函数调用时,每一个关键字形参将被绑定到紧跟在同名键字后面的那个值上。
(foo) -> (NIL NIL NIL)
(foo :a 1 :c 3) -> (1 NIL 3)
(foo :a 1 :b 2 :c 3) -> (1 2 3)
关键字形参也可以提供一个默认值形式以及一个supplied-p 变量名
(defun foo (&key (a 0) (b 0 b-supplied-p) (c (+ a b)))
(list a b c b-supplied-p)
(foo :a 1) -> (1 0 1 NIL)
(foo :b 1 :c 4) -> (0 1 4 T)
(foo :a 2 :b 1 :c 4) -> (2 1 4 T)
如果出于某种原因想让调用者用来指定形参的关键字不同中于实际形参名,那么可以将形参名替换成一个列表,这种风格在想要完全将函数的公共API与其内部细节相隔离时特别有用。
(defun foo (&key ((:apple a)) ((:box b) 0) ((:charlie c) 0 c-supplied-p))
(list a b c c-supplied-p))
(foo :apple 10 :box 20 :charlie 30) -> (10 20 30 T)
6. 混合不同的形参类型
无论何时,当用到多种类型的形参时,它们必须以这样的顺序声明:首先是必要形参,其次是可选形参,再次是剩余形参,最后才是关键字形参。
如果&rest 和 &key 同时出现在形参列表里,那么两件事都会发生----所有剩余的值,包括关键字符本身,都将被收集到一个列表里,然后被绑定到&rest 形参上,而适当的值,也会同时被绑定到&key形参上。
(defun foo (&rest reat &key a b c) (list rest a b c))
(foo :a 1 :b 2 :c 3) -> ((:A 1 :B 2 :C 3) 1 2 3)
7. 函数返回值
RETURN-FROM 特殊操作符,它能够立即以任何值从函数中返回
(defun foo (n)
(dotimes (i 10)
(dotimes (j 10)
(when (> (* i j) n)
(return-from foo (list i j))))))
8. 作为数据的函数--高阶函数
(有待更新)
9. 匿名函数
(有待更新)