1

我正在尝试遍历 am 长度数组中 n 值的所有可能组合。使用 nil 表示空的地方。在此示例中,n 为 2,m 为 3

;; ('a 'b nil) -> ('a nil 'b)
;; (nil 'a 'b) -> signal end of the rep.
;; ('a 'b nil) -> ('a nil 'b) -> (nil 'a 'b) -> Run out of possiblites.
;;
;; ('a 'b nil nil)
(defun next-candidate (candidate)
  (labels ((iter-helper (xs &optional prev-item)
             (if (and (listp xs)
                      (null  (first xs)))
                 (progn
                   (rotatef (first xs) prev-item)
                   candidate)
                 (iter-helper (rest xs) (first xs)))))
    (when (null (first candidate))
      (signal 'no-more-combinations))
    (iter-helper candidate)))


(let ((test (list 1 nil 3)))
  (next-candidate test))
=> (1 1 3) Expected (nil 1 3)

为什么 rotaref 不交换值?

4

2 回答 2

3

我看到输出:(1 1 3).

如果您期望(nil 1 3),那么您应该尝试找出它应该如何将列表的第一个元素设置为NIL. 在函数中设置局部变量prev-itemviaROTATEF根本不会更改列表。

于 2013-08-09T22:43:03.027 回答
2

(1 1 3)像 Rainer 一样得到,原因是 when(rotatef (first xs) prev-item)被调用xsis(nil 3)prev-itemis 1。在那次调用之后,xsis(1 3)和 - 因为xscdrof candidate- 这意味着candidate,返回值 is (1 1 3)

为了让您了解其rotatef工作原理,这是您如何在一个简单的案例中产生预期结果的方法:

(let ((test (list 1 nil 3)))
  (rotatef (first test) (second test))
  test)

rotatef是破坏性的,这意味着当您更改与其他内容共享结构的内容时(如xsand candidate),您将在两个地方看到更改。

这是我认为更接近您正在寻找的东西,尽管我不完全确定。

(defun next-candidate (candidate)
  (labels ((next (xs)
             (if (null (first xs))
                 (signal 'no-more-combinations)
                 (progn
                   (rotatef (first xs)
                            (second xs)
                            (third xs))
                   xs))))
    (next candidate)))
于 2013-08-09T23:03:22.340 回答