ANSI Common Lisp译本笔记4

控制流

区块

区块的基本操作符:progn、block、tagbody

progn:对主体中的每个表达式依次进行求值,返回最后一个表达式的值。

如:

(progn
        (format t "a")
	(format t "b")
	(+ 1 1))

输出为:ab
23


block:像一个带有名字及紧急出口的progn。第一个参数为符号。可在block中使用return-from  符号跳出block。

例子:

(block head
	(format t "one")
	(return-from head 'over)
	(format t "two"))

输出为:one
OVER
由例子可以看出,block之后的符号为block块的名字,通过return-from block名字即可跳出block。
return-from:第一个参数为区块名,第二个参数为:跳出时的返回值
若想不使用块名,跳出当前块,则可以使用return 返回值,即可。
1.许多接收一个表达式主体的操作符都隐含在一个叫做nil区块中。
2.使用defun定义的函数,都隐含在一个与函数同名的区块中。所以,在函数中可用return-from 跳出函数并返回值
语境
用来代替表达式分组的操作符是let
let:接收一个代码主体,允许在代码主体中设置新变量。第一个参数为变量的初始过程。
如:(let ((x 1) (y 1)) (+ x y))→2
let创造出一个新的词法语境,就像C语言中的代码块,在此语境中的变量为局部变量。
注意:由let创建的变量值,不能依赖其他由同一个let创造的变量。

如:

(let ((x 1) 
	  (y x))
	(+ x y))

其中,第一个let创建了一个x变量,可以在let语境内使用,但不能将此变量用于此let中创建另一个变量的初始值。要想使用则需要用let*。

let*例子:

(let* (x 1)
		(y x)
		(+ x y))

输出:2
其中,let*等价于
(let ((x 1)
     (let (y x)
	(+ x y)))

deftructuring-bind:这是一个通用化的let,是一个宏。接收单一变量,接收一个模式:一个或多个变量形成的树,并将它们与某个实际的树所对应部分做绑定。
例子:(destructuring-bind (w (x y) . z)'(a (b c) d e) (list w x y z))→(A B C (D E))

条件
if
格式:if 条件 语句1 语句2
说明:若条件为真,则执行语句1,否则执行语句2

例子:

(defun max-my (x y)
	(if (> x y) x y))

测试代码:

CL-USER> (max-my 1 2)

2

when
格式:when 条件 语句1 语句2 ....
说明:若条件满足则开始执行when中的所有语句,返回最后一条语句的值

例子:

(defun say (flag)
	(when (equal flag "talk")
	  (format t "hello!")
	  (format t "What's your name?")))
测试代码:

CL-USER> (say "talk")
hello!What's your name?
NIL


unless与when类似,when是条件为真,执行语句。 unless是条件为假,执行语句

cond
格式:cond (条件1 语句1 条件2 语句2...)
说明:条件1为真,执行语句1,否则判断条件2是否为真,为真执行语句2,否则判断条件3....

例子:

(defun my-num-range (x)
	(cond ((> x 10) (format t "~A>10~%" x))
		((> x 5) (format t "~A>5~%" x))
		((> x 0) (format t "~A>0~%" x))
		(t (format t "~A<0~%" x))))
测试代码:

CL-USER> (my-num-range 4)
4>0
NIL

其中,cond可以理解为只有当条件为真时,才会停止判断,条件为真的其后的语句。最后一句,应为t永远为真,所以将此句作为缺省的条件式。

case
格式:case 关键字变量 (关键字或关键字列表 语句)...
说明:关键字的值会和下面的每个关键字或在关键字列表中查找,若有相等的则执行其后的语句。缺省子句可用的键值可为t或otherwise。

typecase与case相似,typecase的每个键值应为类型修饰符。第一个参数与键值比较的函数使用typep。


迭代
do
格式:do (变量规格说明的列表) (条件 语句1) 语句2
说明:变量规格的说明列表为:迭代变量名,迭代初始值,下一个迭代值。条件为结束迭代的条件,当满足条件时执行语句1并停止迭代,否则执行迭代体语句,即:语句2。

例子:

(defun do-test (x)
	(do ((i 0 (+ i 1)))
	    ((= i x) 'done)
	  (format t "~A," i)))
测试代码:

CL-USER> (do-test 5)
0,1,2,3,4,
DONE

do*:do*与do的关系相当于let*和let的关系。

dolist

格式:dolist (迭代变量 列表 迭代结束返回值) 迭代体语句
说明:当迭代开始时,会从列表第一个元素开始,依次赋给迭代变量,然后执行迭代体语句,当迭代到列表最后一个元素之后,则返回迭代结束返回值。迭代结束返回值也可以是一个语句。

例子:

(defun dolist-test (lst)
  	(dolist (x lst (format t "~%list over"))
		(format t "~A," x)))
测试代码:

CL-USER> (dolist-test '(1 2 3 4))
1,2,3,4,
list over
NIL


dotimes
格式:dotimes (迭代变量 N 迭代结束返回值) 迭代体语句
说明:给定一个整数N,则会从整数0开始,直到N-1

例子:

(defun dotimes-test (n)
	(dotimes (x n 'over)
		(format t "~A," x)))
测试代码:

CL-USER> (dotimes-test 4)
0,1,2,3,
OVER


多值
values:将传入的参数返回。若将values作为函数的最后一个表达式,则values返回的值将作为函数返回值

测试代码:

CL-USER> (values 'a 1 (+ 1 1))
A
1
2

multiple-value-bind:接受多个值。若变量的数量大于数值的数量,剩余变量为nil。若数值的数量大于变量的数据,则多余的值舍去。

测试代码:

CL-USER> (multiple-value-bind (x y z) (values 1 2 3) (list x y z)) 
(1 2 3)
CL-USER> (multiple-value-bind (x y z) (values 1 2) (list x y z))
(1 2 NIL)
CL-USER> (multiple-value-bind (x y z) (values 1 2 3 4) (list x y z))
(1 2 3)


multiple-value-call:将多值作为参数传给函数。第一个参数为函数,第二个参数为多值

测试代码:

CL-USER> (multiple-value-call #'+ (values 1 2 3))
6


mutiple-value-list:将传入的多值创建一个列表并返回。


中止


catch与throw
使用catch定义一个标签,在代码任何地方,一个带有特定标签的throw都会导致catch的表达式直接返回。

例子:

(defun sup()
	(catch 'quit
	 (sub)
	(format t "aaa")))
(defun sub()(throw 'quit 'done))
测试代码:

CL-USER> (sup)

DONE

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值