【问题标题】:How can I do two or more instructions in a loop in common-lisp?如何在 common-lisp 的循环中执行两个或多个指令?
【发布时间】:2016-09-06 20:08:04
【问题描述】:

我想知道这段代码有什么问题。假设 *corpus 是一个单词列表(“at” “the” ...),这段代码试图将它们保存在一个哈希表中(单词重复-单词)

(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)))

如果单词在哈希表中,只需增加 1,否则添加一个新对。

【问题讨论】:

  • 请正确格式化您的代码(例如使用 Emacs)。这对于我们能够阅读您的代码是必要的。例如,你肯定在do 之后有一个虚假的(,但我不知道你是否曾经关闭它(不是说它是相关的)。此外,您应该粘贴您看到的确切错误消息。
  • gethash 采用可选的第三个参数 default,如果在哈希表中找不到密钥,则返回该参数。 incf 会很高兴地增加这个默认值,然后用新的键更新哈希表。因此,您在外循环中所要做的就是(incf (gethash x h 0))

标签: loops common-lisp hashtable nested-loops


【解决方案1】:

你想迭代一个词库;对于每个单词 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 的当前值。请注意,GETHASH 提供了一个默认表单,以防没有值绑定到给定键。在这里,我只需要输入零,以便增量适用于所有情况。一开始我没看,但是来自 Terje D. 的this comment 已经说过了。

示例

(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) 

【讨论】:

    【解决方案2】:

    CL 中的块如下所示:

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

    这可以用于需要一个表达式的地方,因为一个块就是一个表达式。 In loop do 后面可以跟一种或多种复合形式(函数调用、宏调用、特殊形式……):

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

    【讨论】:

    • @RainerJoswig 已修复。傻我。如果我至少保持一致:-p
    • 另外:do 关键字后面可以跟多个形式,因此progn 不是必需的。
    • @TerjeD。谢谢。我今天也学到了一些东西。我一直使用progn 并且从未真正考虑过它。 loop 宏肯定有它的惊喜。
    猜你喜欢
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 2019-05-10
    相关资源
    最近更新 更多