宏:标准控制结构

引导

lisp和其他语言一样,有条件表达式,垃圾收集,但是lisp的宏系统却始终使他保持了在语言风格上的独特性。lisp的宏和任何语言的“宏”是不一样的。这个东西很难解释。

语言都有一个“核心”语言实现的标准功能库(java的JDK),如果某些功能没有定义在标准库中,可以自己实现。(求平凡实现列子)

。。。。。。

WHEN和UNLESS

最基本的条件执行形式是IF特殊操作符,其基本形式是:如果x成立,那么执行y,否则执行z。

(if condition then-form [else-form])

condition被求值,如果其值非NIL,那么then-form会被求值并返回其结果。否则,如果有else-form,他将被求值并返回其结果。如果condition是NIL并且没有else-form,那么IF返回NIL。(condition是判断条件,如果为nil就返回then-form的值,否则要是有else-form就返回else-form的值。如果只有condition并且值是nil就返回nil

1
2
3
4
5
6
CL-USER> (if (> 2 3) "YES" "no")
"no"
CL-USER> (if (> 2 3) "yes")
NIL
CL-USER> (if (> 3 2)"yes" "no")
"yes"

有一个情况不行,当条件成立,连续执行两个就不可以,因为会被当成else执行。要想在条件语句执行多个就必须使用progn特殊操作符。

1
2
3
4
(if (a)
(progn
(into)
(update)))

如上面,这样才会在a成立的时候执行into再执行update。

其lisp提供了一个标准宏WHEN 就是解决这个问题的。上面的可以写成这个样子

1
2
3
(when (a)
(into)
(update))

如果它没有被内置到标准库中,你也可以像下面这样用一个宏来定义WHEN

1
2
(defnacro when (condition &rest body)
`(if ,condition (progn ,@body)))

与WHEN宏同系列的另一个宏是UNLESS 它取相反条件,只有条件假的时候才求值其形式体。

1
2
(defnacro when (condition &rest body)
`(if (not ,condition) (progn ,@body)))

其实上面的定义不对,因为重新定义when所在的common-lisp包中的名字是非法的,如果非要这么做,可以修改名字,比如my-when

COND

1
2
3
4
5
(if a
(do-x)
(if b
(do-y)
(do-z)))

多重分支用if是可以,但是比较丑陋

如果子句再分很多就更丑了,但是lisp提供了一个用于表达多重分支条件的宏COND基本结构如下

1
2
3
4
5
6
7
(cond
(test-1 form*)
(test-2 form*)
.
.
.
(test-N form*))

AND、OR和NOT

循环

DOLIST和DOTIMES

DO

强大的LOOP