循环作为表达

与今天使用的几乎所有其他编程语言中的循环不同,Common Lisp 中的 LOOP 可以用作表达式:

(let ((doubled (loop for x from 1 to 10
                     collect (* 2 x))))
    doubled) ;; ==> (2 4 6 8 10 12 14 16 18 20)

(loop for x from 1 to 10 sum x)

MAXIMIZE 使 LOOP 返回已评估的最大值。MINIMIZEMAXIMIZE 相反。

(loop repeat 100
      for x = (random 1000)
      maximize x)

COUNT 告诉你在循环期间表达式计算到非 NIL 的次数:

(loop repeat 100
      for x = (random 1000)
      count (evenp x))

LOOP 还具有 someeverynotany 功能的等价物:

(loop for ch across "foobar"
     thereis (eq ch #\a))

(loop for x in '(a b c d e f 1)
    always (symbolp x))

(loop for x in '(1 3 5 7)
    never (evenp x))

…除了它们不限于迭代序列:

(loop for value = (read *standard-input* nil :eof)
   until (eq value :eof)
   never (stringp value))

LOOP 值生成动词也可以用 -ing 后缀编写:

(loop repeat 100
      for x = (random 1000)
      minimizing x)

也可以将这些动词生成的值捕获到变量(由 LOOP 宏隐式创建)中,这样你就可以一次生成多个值:

 (loop repeat 100
     for x = (random 1000)
     maximizing x into biggest
     minimizing x into smallest
     summing x into total
     collecting x into xs
     finally (return (values biggest smallest total xs)))

你可以拥有多个 collectcount 等子句,它们会收集到相同的输出值。它们将按顺序执行。

以下内容将关联列表(可以与 assoc 一起使用)转换为属性列表(可以与 getf 一起使用):

(loop for (key . value) in assoc-list
      collect key
      collect value)

虽然这是更好的风格:

(loop for (key . value) in assoc-list
      append (list key value))