您的位置:首页 > 其它

CLisp 7:用LISP的基本规则实现if

2012-08-11 21:17 211 查看
LISP有7个基本规则,或7个基本函数,这里用他们实现if,在此过程中学一些知识

为了覆盖系统自带的if,我们将名称改成if.(后面加一个点号)

首先,定义一个名词为if.的函数

(defun if. (test success &optional fail)

(cond ((eq fail nil) (cond (test success)))

('t (cond (test success) ('t fail)))))

测试一下能不能工作

(if. t (print 'if) (print 'else))

if

else

if

输出的结果明显不正确

因为调用函数if.前,对输入的所有参数进行求值,即调用if.前就执行了print函数。

接着,把函数if.改成宏if.,避免对输入参数求值

(defmacro if. (test success &optional fail)

`(cond ((eq ,fail nil) (cond (,test ,success)))

('t (cond (,test ,success) ('t ,fail)))))

测试一下能不能工作

(if. t (print 'if) (print 'else))

else

if

if

输出的结果也不正确

问题出在(eq ,fail nil)上,宏展开后变成(eq (print 'else) nil),即执行了print函数。

要改变判断optional参数是否有效的方式

(defmacro if. (test success &optional (fail nil fail-p))

`(cond (fail-p (cond (,test ,success) ('t ,fail)))

('t (cond (,test ,success)))))

测试时出现错误 COND: variable FAIL-P has no value

不能用optional参数,改用函数重载,即定义两个if.宏

(defmacro if. (test success)

`(cond (,test ,success)))

(defmacro if. (test success fail)

`(cond (,test ,success) (t ,fail)))

到此为止能够通过测试,和系统自带的if有相同的输出

今天发现上面用option的实现存在问题,不应该在第一个cond表达式前面写反引号,这样做将判断有没有fail分支的代码带到了最终生成的代码中。正确的实现如下,这样不用写重载的两个if.宏

(defmacro if. (test success &optional fail)

(cond ((eq nil fail) `(cond (,test ,success)))

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