1 定义函数
(defun name (parameter*)
body-form*)
body可由任意Lisp表达式构成,它们将在函数调用时依次求值,而最后一个表达式的值将被返回。return-from可以从函数任意位置立即返回。
2 形参列表
函数定义的括号中可以提供一系列的形参,当函数调用时,必须为它的每一个必要形参都提供一个实参。每个形参被绑定到对应的实参上。如果函数以过少或过多的实参来调用,Lisp会报错。
参数也可以有可选形参,或者可以用单个形参绑定到含有任意多个参数的列表上。最后,参数还可以通过关键字而非位置来映射到形参上。
3 可选形参
可选形参放在必要形参之后,中间使用&optional分隔,对于可选形参可以提供初始值,若无提供则为NIL。
(defun foo (a b &optional c d (e 10))
(list a b c d e))
在形参列表中,可选形参还可以引用前面出现的必要形参,例如下面的矩形生成器,通常只生成正方形。
(defun make-rectangle (width &optional (height width))
...)
有时需要在运行时知道一个可选形参是调用者明确指定还是使用了默认值,可以在形参标识符的默认值表达式后添加一个变量名来实现。此变量在调用者实际提供实参时绑定到真值,否则为NIL。约定此变量的名字为对应形参后带-supplied-p后缀。
(defun foo (a b &optional (c 3 c-supplied-p))
(list a b c c-supplied-p))
4 剩余形参
Lisp允许在符号&rest后包括变参列表,任何满足了必要和可选形参之后的其余所有实参将被收集到一个列表里成为此形参的值。例如加法函数add的形参列表看起来如下:
(defun add (&rest numbers)
...)
5 键值形参
可以按键值的形式来传递特定的参数,可以加上符号&key以及任意数量的键值形参标识符即可。
(defun foo (&key a b c)
(list a b c))
(foo :a 1 :c 3) ;;(1 NIL 3)
键值形参也可以使用可选参数,也支持判断是否为显式提供。
6 函数返回值
return-from支持从当前代码块中返回,其需要指定要退出的一个函数名。
7 高阶函数
在Lisp中,函数的使用是通过名字进行调用,但函数也是一种对象。函数在定义的时候同时也创建了一个新的函数对象。
操作符Function可以根据名字返回此函数对象,其简写为#',函数的名字不需要被引用。
Lisp提供了两个使用函数对象进行调用的函数:
(FunCall funObj parm*) 将函数对象应用到参数上,参数个数为已知的。
(Apply funObj list*) 将参数列表传递给函数对象,参数作为列表传递给函数,个数未知。
8 匿名函数
为了编写一些只使用一次的函数,可以使用lambda表达式。
(lambda (param*)
body-form*)
lambda的另一个作用是创建捕捉创建时信息的闭包函数。