Lisp 函数

LISP笔记(函数)(LISPNULL在书中一般表示NIL, 这里用了小写nil)

函数是一种对代码比特进行抽象的标准方式

函数的一般定义:

(defun name (parameter*)
“Optional documentation string.”
Body-form*)

函数名用-分隔符更具有lisp风格。

Lisp(helloworld程序): (defun hello-world() (format t “hello, world”)).

一:可选形参,关键字(optional

1)可选形参,关键字(optional

(defun foo (a b &optional c d) (list a b c d))
(foo 1 2) -> (1 2 nil nil)
(foo 1 2 3) -> (1 2 3 nil)
(foo 1 2 3 4) -> (1 2 3 4)

2)也可以为可选形参提供指定默认值而不是NIL

(defun foo (a &optional (b 10)) (list a b))

(foo 1 2) -> (1 2)

(foo 1) -> (1 10)

3)也可以: 

(defun make-rectangle (width &optional (height width)) ...)

除非明确指定否则height形参带有和width形参相同的值

4)判断可选形参是否用了默认值: -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)
(foo 1 2 4) -> (1 2 4 T)

二:剩余形参 (可变数量的实参)

1)剩余形参,关键字:&rest

满足了必要和可选形参之后的其余所有实参被收集到一个列表里成为该&rest形参的值

Format函数为:(defun format (stream string &rest values) ...)

+函数则为: (defun + (&rest numbers) ...)

三:关键字形参关键字:&key

1)关键字形参(&key)

(defun foo (&key a b c)
(list a b c))
(foo) -> (nil nil nil)
(foo :a 1) -> (1 nil nil)
(foo :a 1 :c 3) -> (1 nil 3)
(foo :a 1 :c 3 :b 2) -> (1 2 3)

2)提供默认值形式及一个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) -> (0 1 1 T)
(foo :a 2 :b 1 :c 4) -> (2 1 4 T)

3)将形参名替换成一个列表,调用函数时使用关键字以及用作形参的名字

(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) //用在API与其内部隔离

四:函数返回值

RETURN-FROM

(defun foo (n)
(dotimes (i 10)
(dotimes (j 10)
(when (> (* i j) n)
(return-from foo (list i j))))))

五:高阶函数 (函数是一种对代码比特进行抽象的标准方式)

Defun 定义一个函数作了两件事:创建一个新的函数对象以及赋予其一个名字。

1)获取一个函数的方法 FUNCTION  (#FUNCTIONDE 语法糖)

(defun foo (x) (* 2 x))
(function foo) == #’foo

2)调用函数 FUNCALL and APPLY

(foo 1 2 3) == (funcall #’foo 1 2 3)

然而,当实参列表只在运行期时,FUNCALL的表现不佳。

(foo (first plot-data) (second plot-data) (third plot-data) (fourth plot-data))

这样的写法令人讨厌

这就是需要APPLY的原因了

Apply 的第一个参数是一个函数对象,在这之后是一个列表

(apply #’foo plot-data)

Apply还接受孤立的实参,只要最后一个参数是一个列表

(apply #’foo #’exp plot-data)

六:匿名函数 (LAMBDA

(lambda (parameters) body)
(funcall #’(lambda (x y) (+ x y)) 2 3) -> 5

甚至还可以将LAMBDA表达式用作函数名

((lambda (x y) (+ x y)) 2 3) -> 5
(defun double(x) (* 2 x))

(foo #’double 1 2)不如(foo #’(lambda (x) (* 2 x)) 1 2)清晰简单

LAMBDA还有闭包作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值