如何在 common-lisp 的循环中执行两条或更多条指令?

How can I do two or more instructions in a loop in common-lisp?

我想知道这个 code.Assume *语料库是一个单词列表("at" "the" ...),这段代码试图将它们保存在一个hash-table (word times-repeated-word)

(defparameter h (make-hash-table))
(defparameter ex 0)
(loop for x in *corpus
      do ((setf ex 0)
          (loop for y being the hash-keys of h
                if (equal x y) do ((incf (gethash y h)) (setf ex 1)))
                if (eql ex 0)
                do (setf (gethash x h) 1)))

如果单词在散列中-table只需增加 1,否则添加新的一对。

CL 中的一个块如下所示:

(progn
  expression1
  expression2
  ...
  expressionn); the result of the form is result of expressionn

这可以用于需要一个表达式的地方,因为一个块是一个表达式。在循环 do 后面可以跟一个或多个复合形式(函数调用,宏调用,特殊形式,...):

(loop :for element :in list
      :do expression1
          expression2
          expression3)

您想迭代语料库;对于每个单词 w,如果 w 映射到某个哈希中的整数 n,您想要增加该数字,以便 w 映射到 n+1;否则,您想将该词映射到 1.

基本上,您想这样做:

(defun increment-corpus (corpus hash)
  (map nil
       (lambda (word)
         (incf (gethash word hash 0)))
       corpus))
  • 我正在使用 MAP 以便我可以遍历任何单词序列,而不仅仅是列表。

  • MAP的result-type是NIL,因为我不关心结果,只想做副作用

  • 所应用的函数只是将绑定到 word 的当前值递增。请注意,来自 Terje D. 的 GETHASH provides a default form to be evaluated in case no value is bound to the given key. Here, I just need to put zero so that the increment works in all cases. I didn't read it at first, but 已经说过了。

例子

(defparameter *hash* (make-hash-table :test #'equal))

(defun test (&rest words)
  (increment-corpus words *hash*)
  (maphash (lambda (&rest entry) (print entry)) *hash*))

哈希最初是空的。

> (test "a" "b" "c" "d")

("a" 1) 
("b" 1) 
("c" 1) 
("d" 1)

> (test "a")

("a" 2) 
("b" 1) 
("c" 1) 
("d" 1)

> (test "a" "b" "c" "x")

("a" 3) 
("b" 2) 
("c" 2) 
("d" 1) 
("x" 1)