从dolist循环返回列表,而不是返回NIL

时间:2013-11-07 15:07:34

标签: lisp common-lisp

你能帮我解决一下我的代码,我不明白为什么它没有返回我的wireList,它只是返回NIL

(defun table-wires-position(inputTable inputPosition)
   (let ((wireList () ))
     (dolist (x (table-wires inputTable) wireList)
        (if (or (equal-position-p (wire-OriginCoin x) inputPosition) 
                (equal-position-p (wire-destinCoin x) inputPosition))
                   (cons x wireList)))))

3 个答案:

答案 0 :(得分:7)

首先,请注意您在编写代码时技术上是正确的(the best kind of correct):

(let ((wireList ()))
  (dolist (x (table-wires inputTable) wireList)
    …)

这确实意味着dolist正在返回wireList。问题标题“从dolist循环返回列表,而不是返回NIL”有点误导,因为:(i)nil 一个列表,所以你要返回一个列表; (ii)您 返回wireList。问题是您在执行wireList期间实际上没有修改dolist。函数cons只需返回一个新的cons单元格;它不会修改地点,因此您不会修改wireList。您可以使用push代替,如下面的代码所示。由于您使用的if没有其他部分,因此您可以使用when

(defun table-wires-position(inputTable inputPosition)
  (let ((wireList ()))
    (dolist (x (table-wires inputTable) wireList)
      (when (or (equal-position-p (wire-OriginCoin x) inputPosition) 
                (equal-position-p (wire-destinCoin x) inputPosition))
        (push x wireList))))) ; or (setf wireList (cons x wireList))

在样式节点上,我经常使用&aux variables来表示这些结果变量;它避免了嵌套程度:

(defun table-wires-position (inputTable inputPosition &aux (wireList '()))
  (dolist (x (table-wires inputTable) wireList)
    (when (or (equal-position-p (wire-OriginCoin x) inputPosition) 
              (equal-position-p (wire-destinCoin x) inputPosition))
      (push x wireList))))

请注意,通过push元素进入列表,您将从inputTable开始按相反的顺序获取它们。如果您愿意,可以通过返回(nreverse wireList)来获得相同的顺序。更好的是,因为你真的只是删除了删除了某些元素的列表,所以你也可以使用remove-if-not

(defun table-wires-position (inputTable inputPosition)
  (remove-if-not #'(lambda (x) 
                     (or (equal-position-p (wire-OriginCoin x) inputPosition) 
                         (equal-position-p (wire-destinCoin x) inputPosition)))
                 inputTable))

答案 1 :(得分:1)

约书亚的回答是这里的方法,但作为附录,这是使用循环宏的版本。

(defun table-wires-position (input-table input-position)
  (loop :for x :in input-table 
     :if (or (equal-position-p (wire-origin-coin x) input-position) 
             (equal-position-p (wire-destin-coin x) input-position))
     :collect x))

也不要使用camelcase名称,因为符号不区分大小写,因此以下所有相同

inputPosition INputPosition INPUTPOSITION iNpUtPoSiTiOn

总是使用例如输入位

答案 2 :(得分:1)

小补充:

如果宏在do中以dolist开头,则只需迭代并对副作用进行迭代。因此,如果需要,将迭代结果放在某处是用户任务。

如果它以collect开头或者在正文的某处允许collect子句,那么它应该返回一个迭代结果列表。 loop宏是一个这样的构造,但是可以在库或书籍中找到其他迭代构造。