如何在lisp中创建对列表?

时间:2012-11-27 22:41:00

标签: list lisp

我正在尝试将对子列表作为家庭作业的一部分。

我尝试过(在函数中间某处)

(setq list1 (append list1 (cons n1 n2)))

由于某些原因我不明白,这对第一对很好,但是当我尝试追加第二对时,会弹出这个错误:

  

*** - APPEND:正确的列表不得以2

结尾

我该如何解决这个问题?

所以,继续这个主题,感谢答案,我能够纠正我的问题。但是出现了一个新的,我认为它与它有关。所以,我有这个功能:

(defun action(state)
(let ((list_actions '())
      (limNumActions (1- (list-length state)))
      (limNumSubActions 0)
      (numActions 0)
      (numSubActions 0))
  (loop for numActions from 0 to limNumActions do
    (setq limNumSubActions (1- (list-length (nth numActions state))))
    (loop for numSubActions from 0 to limNumSubActions do
      (setq list_actions (append list_actions
        (list (cons numActions numSubActions))))
      (print 'list_actions)
      (print list_actions)))))

我使用print函数作为简单的“调试器”。它返回:

 LIST_ACTIONS 
 ((0 . 0)) 
 LIST_ACTIONS 
 ((0 . 0) (0 . 1)) 
 LIST_ACTIONS 
 ((0 . 0) (0 . 1) (1 . 0)) 
 LIST_ACTIONS 
 ((0 . 0) (0 . 1) (1 . 0) (1 . 1)) 
 NIL

这正是我期待的结果! NIL部分除外...您能否理解为什么列表list_actions最后是NIL

3 个答案:

答案 0 :(得分:1)

append有两个列表,不是列表和单个元素。在append中使用它之前,您需要在对中放置一个列表。

目前该对被列为列表的一部分,这使得列表不正确并导致第二个附加失败,因为不正确的列表没有完全附加到的结尾。

答案 1 :(得分:1)

代码可以更加简洁地表达如下:

(defun action (state)
  (let ((list-actions '()))
    (loop for i from 0 for state-i in state do
      (loop for j from 0 below (length state-i) do
        (setf list-actions (append list-actions (list (cons i j))))
        (print 'list-actions)
        (print list-actions)))
    list-actions))

如果只需要结果,它可以更短(并且成本更低,因为它不使用昂贵的append功能),

(defun action (state)
  (loop for i from 0 for state-i in state append
    (loop for j below (length state-i) collect (cons i j))))

答案 2 :(得分:0)

我试图稍微改进你的例子+编写一个使用不同的版本,但IMO更习惯于解决这个问题:

;; Your original version, but cleaned up a bit
(defun action (state)
  (loop with list-actions = nil
     with lim-num-actions = (1- (list-length state))
     with lim-num-sub-actions = 0
     for num-actions from 0 to lim-num-actions
     do (setq lim-num-sub-actions (1- (list-length (nth num-actions state))))
       (loop for num-sub-actions from 0 to lim-num-sub-actions
          do (push (cons num-actions num-sub-actions) list-actions)
            (format t "~&~s ~s" 'list-actions list-actions))
     finally (return list-actions)))

;; A more traditional approach (if you want to use iteration)
(defun action (state)
  (reverse 
   (loop for i in state
      for j from 0
      collect (cons j 0))))

;; Using a nice library to do iteration
(ql:quickload "iterate")
;; Note, you could do (in-package :iterate)
;; to lose `iterate:' prefix to make it even shorter
(defun action (state)
  (iterate:iter
    (iterate:for i #:on state)
    (iterate:for j #:from 0)
    (iterate:accumulate (cons j 0) #:by #'cons)))

;; Just another way to do this, using `reduce'
(reduce #'(lambda (a b)
            (declare (ignore b))
            (cons (cons (1+ (caar a)) 0) a))
        (cdr (mapcar #'list '(1 2 3 4 5)))
        :initial-value '((0 . 0)))

(action (mapcar #'list '(1 2 3 4 5)))