控制流

Table of Contents

1. 逻辑运算

1.1. and

(and &rest forms)

所有 form 计算如果都不为 nil,返回最后个 form 的值,否则返回 nil。

(and 1 2 3)                             ; => 3
(and 1 2 nil)                           ; => NIL

2. do

(do varlist endlist &body body)

循环。

参数 varlist 用来定义变量,可指定初始值以及步长:

(i) ; 定义变量 i
(i 0) ; 定义变量 i,并初始为 0
(i 0 (1+ i)) ; 定义变量i并初始为 0,每次循环都会调用 +1 进行自加操作

endlist 指定循环结束的条件,以及返回值:

((> i 100)) ; 结束条件为 i 大于 100
((> i 100) i) ; 指定 do 循环的返回值 i

例:从 1 加到 100,过程中打印 i 的值,最后表达式返回相加结果:

(do ((i 0 (1+ i))
     ;; 变量n作为累加器
     (n 0 (+ n i)) )
    ((> i 100) n)
  (print i))

3. dotimes

(dotimes (var count &optional result) &body body)

按次数循环。

(dotimes (i 100 i)
  (print i))

result 参数可以指定 dotimes 的返回结果:

(dotimes (i 10 'bye)
  (print i))

4. dolist

(dolist (var list &optional result) &body body)

迭代一个 list 对象。

  • var:参数存储每次取到 list 元素的值。
  • list:遍历的对象。
  • result:可选参数,指定表达式。
(dolist (i '(1 2 3 4 5))
  (print i))

5. return

return 能跳出循环,示例:

(dolist (i '(1 2 3 4 "5" 6 7))
  (when (stringp i)
    (format t "found a string: ~S" i)
    ;; 跳出并返回 NIL
    (return nil)))

6. return-from

定义:

(return-from block-name [value])

可以从指定的块名中退出,比如嵌套循环中,当满足某个条件后想退出最外层的循环,示例:

(block loop1
  (dotimes (i 10)
    (dotimes (n i)
      (format t "~&i:~A n:~A" i n)
      ;; 如果这里用 return,只会退出当前的循环,第一层循环仍然继续
      (when (= i 5)
        (return-from loop1)))))

7. progn

(progn &rest forms)

执行多个表达式,并将表达式最后个值作为返回值。

Q:什么时候该用 progn,什么时候用 block?

A:如果需要突然退出,使用 block,其他时候则用 progn。

(progn (print 1) (print 2) 3)
;; 输出:
;; 1
;; 2
;; 3

8. multiple-value-prog1

(multiple-value-prog1 values-form &rest forms)

执行多个表达式,并把第一个表达式的执行结果作为返回结果。

(multiple-value-prog1
    (1+ 1)
  (print "a")
  (print "b"))

;; 输出:
;; "a"
;; "b"
;; 2