您的位置:首页 > 其它

CLisp 8:用LISP的基本规则实现while

2012-08-12 21:19 489 查看
要实现的while控制结构如下(用C/Java语言描述):

while (test) body;

要实现循环,要么用递归函数,要么用goto。用goto的等效实现如下:

label:

if (test)

{

body;

goto label;

}

LISP的七个基本规则中没有goto,要介绍CLisp的新操作符tagbody

tagbody将多条LISP语句组在一起,按顺序执行,例如

(tagbody

(print 'a)

(print 'b)

(print 'c))

在tagbody里面可以加标签、和go语句

(tagbody

(print 'a)

(go label_x)

(print 'b)

label_x

(print 'c))

上面语句不会打印字母B,注意标签后面不需要冒号

用tagbody实现的while语句

(tagbody

while_label

(cond (test body (go while_label)))

例如打印1~10的循环

x=0

while (x<10) {

++x;

print (x); }

可以实现为

(setq x 0)

(tagbody

while_label

(cond ((< x 10) (setq x (+ 1 x))

(print x)

(go while_label))))

最后实现while宏

(defmacro while. (test &rest body)

`(tagbody

while_label

(cond (,test ,@body (go while_label)))))

用while宏重新实现打印1~10的循环

(setq x 0)

(while. (< x 10)

(setq x (+ 1 x))

(print x))

但是,这个while宏存在陷阱,调用的代码里面不应该看到标签while_label,但确确实实能

够看到。

(setq x 0)

(while. (< x 10)

(setq x (+ 1 x))

(go while_label)

(print x))

不管怎么说,这终究是个问题。可以用gensym生成一个唯一的标识符,代替写死的

while_label。

(defmacro while. (test &rest body)

(let ((label (gensym)))

`(tagbody

,label

(cond (,test ,@body (go ,label))))))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: