Common Lisp语法——函数定义

Common Lisp通过DEFUN宏来定义新的函数

(defun name (parameter*)
  "optional documentation string."
  body-form*)
这里函数的名字几乎可以是任意的符号/字符组合,一般是小写字母和连字符。如:

(defun hello-world () (format t "hello, world~%"))

可选参数(optional parameters)


(defun foo (p1 p2 &optional p3 p4) (list p1 p2 p3 p4))
&optional后的参数p3 p4都是可选的,运行该函数后的结果可能如下:

(foo 1 2)         ->        (1 2 NIL NIL)
(foo 1 2 3)       ->        (1 2 3 NIL)
(foo 1 2 3 4)     ->        (1 2 3 4)

还可以通过如下方式指定可选参数的默认值

(defun foo (p1 &optional (b 10)) (list a b))
运行该函数后的结果可能如下:

(foo 1)    ->    (1 10)
(foo 1 2)  ->    (1 2)

如果需要判断可选参数是否由客户端(caller)指定了值,可以通过在默认值表达式后添加一个特殊的变量来获取。这个变量的名字为可选参数名加上后缀"-supplied-p",当客户端指定了具体值,该变量为true,否则为NIL。如:

(defun foo (p1 &optional (p2 2 p2-supplied-p)) (list p1 p2 p2-supplied-p))

可能的运行结果为:

(foo 1)   ->  (1 2 NIL)
(foo 1 0) ->  (1 0 T)
(foo 1 2) ->  (1 0 T)

变长参数(Rest Parameters)

(defun foo (p1 &rest others) (list p1 others))
函数FOO必须的参数个数为1,其他剩余的参数将组成一个list存到&rest后的变量others中。运行该函数的可能结果:

(foo 1 'a 'b 'c)  -> (1 (A B C))

可变长参数的最大支持的个数以来不同的lisp实现,但是最少都支持50个。

关键字参数(Keyword Parameters)

(defun foo (&key p1 p2 p3) (list p1 p2 p3))
&key后的参数为keyword parameters,可以有任意个数。当FOO被调用时,每个keyword parameter都被绑定为了指定的值(或默认值),同时由于keyword parameters被标签化了,所以可以任意顺序的指定它们的值,如:

(foo)                        -> (NIL NIL NIL)
(foo :p1 1 :p2 'a)           -> (1 'a NIL)
(foo :p1 1 :p3 3)            -> (1 NIL 3)
(foo :p2 2 :p1 'first :p3 3) -> (FIRST 2 3)
也可以用类似设定optional parameter默认值的方式设定keword parameters的默认值:

(defun foo (&key (p1 1) (p2 2 p2-supplied-p) (p3 (+ p1 p2)))
  (list p1 p2 p3 p2-supplied-p))
可能的运行结果如下:

(foo)                      -> (1 2 3 NIL)
(foo :p2 2)                -> (1 2 3 T)
(foo :p1 10 :p2 20 :p3 30) -> (10 20 30 T)

混合不同类型的参数

可以在函数的参数列表中混合以上类型的参数,但是不太常用。但是他们须遵循如下顺序:1、必要的参数;2、可选参数(optional parameter);3、可变参数(rest parameter);4、关键字参数(keyword parameter)。如需用时再补充。

函数返回值

所有函数的默认返回值其最后一个表达式的值。也可以通过RETURN-FROM(后续补充)立即返回特定的值。

将函数作为数据(Functions As Data)

可以类比为C语言中的函数地址,要获取function object,可通过FUNCTION操作符或#':

(function foo)  ;等价于 #'foo
当获取到function object后,可以通过FUNCALL或APPLY调用该函数。

FUNCALL,当在编码时已知将要传递给函数的参数个数时使用;

APPLY,则是将函数所需要的参数打包成一个list出入。

(defun foo (p1 p2) (format t "~d(P1)  ~d(P2)~%))
(funcall #'foo 1 2)  ; 输出为:1(P1) 2(P2)
(apply #'foo '(10 20)) ; 输出为:10(P1) 20(P2)

匿名函数(Anonymous Functions)

(lambda parameters) body)
比如:

(funcall #'(lambda (x y) (+ x y)) 2 3)   ->  5

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值