Common Lisp语法——标准控制宏

WHEN和UNLESS

先来了解下IF表达式:

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

其行为就是:当condition为non-NIL时则运行then-form并返回其值,否则运行else-form并返回其值。

(if (> 2 3) "yes" "no")   -> "no"
(if (> 2 3) "yes")        -> NIL
(if (> 3 2) "yes" "no")   -> "yes"
但是稍显不足之处在于IF表达式中的then-form和else-form都是single Lisp form。所以如果想顺序执行某个分支中的所有语句,只能如下形式:

(if (spam-p current-message)
  (progn 
    (file-in-spam-folder current-message)
    (update-spam-database current-message)))
这里的PROGN操作符,可按序执行其内部的任意数目的表达式,并以最后一个表达式的值作为PROGN表达式的值返回。

在Common Lisp中提供了宏WHEN以简化上面的代码:

(when (spam-p current-message)
  (file-in-spam-folder current-message)
  (update-spam-database current-message))
WHEN的定义如下:

(defmacro when (condition &rest body)
  `(if ,condition (progn ,@body)))
与WHEN相对应的一个宏UNLESS的定义如下:

(defmacro unless (condition &rest body)
  `(if (not ,condition) (progn ,@body)))

COND

在使用IF表达式编程时,可能有这样的情况:if a do x, else if b do y, else do z.

这时可以用COND宏来简化代码:

(cond 
  (test-1 form*)
  (test-2 form*)
      .
      .
      .
  (test-N form*)) 

AND、OR和NOT

NOT是系统函数,但是它与AND和OR联系非常紧密。它是单参数函数,当参数为NIL时返回T,否则返回NIL。

AND宏按顺序对其所有子表达式进行求值,一旦某个子表达式为NIL则立即返回,后面的子表达式均不在求值。

OR宏也是按顺序对其所有子表达式进行求职,一旦某个子表达式为non-NIL则立即返回,后面的子表达式均不在求值。

(not nil)              -> T
(not (= 1 1))          -> NIL
(and (= 1 2) (= 3 3))  -> NIL
(or (= 1 2) (= 3 3))   -> T

Looping

(dolist (var list-form)
  body-form*)
如果要在loop中途退出循环,可以使用RETURN,如:

(dolist (x '(1 2 3)) (if (> x 2) return) (format t "~d " x))  ;输出为: 1 2

DOTIMES是一个计数循环控制宏:

(dotimes (var count-form)
  body-form*)
其中count-form必须能被求值为整数。var的范围为:[0, count-form)。如:

(dotimes (i 10) (if (> i 3) (return i) (format t "~d " i)) ; 输出为:1 2 3,表达式的返回值为4

由于DOLIST和DOTIMES都只支持一个循环变量,有时不够灵活,可以使用DO宏以支持任意的循环变量,并获取完全的循环控制能力。

(do (variable-definition*)
    (end-test-form result-form*)
  statement*)
每个variable-definition引入的变量仅在循环内可见,单个变量定义的list包括三个元素:

(var init-form step-form)
当end-test-form所求得的值为true时,result-form会被求值,并且最后一个result form将会作为DO表达式的返回值。如:

(do ((i 0 (1+ i)))  ; 输出为: 1 2 3 4
    ((>= i 4))      ; DO表达式的返回值为NIL
  (format t "~d " i)) 

LOOP宏,以其简单和扩展性著称,简单是因为它没有绑定任何变量:

(loop
  body-form*)
同样地,在LOOP表达式内部可以通过RETURN跳出循环。

你可能感兴趣的:(Common,Lisp)