2012-11-27 75 views
0

我正在嘗試做一個列表作爲家庭作業的一部分。如何在lisp中創建對列表?

我想這樣做(在函數的中間位置)

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

出於某種原因,我不明白,這正常工作與第一對,但我嘗試添加第二對,這個錯誤彈出:

*** - APPEND: A proper list must not end with 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

+0

僅供參考:請勿添加作業標籤。它已經過時並正在被刪除。 – Bart

+1

感謝您的信息 – FriedRike

+0

所以,也許我應該在第一個循環結束時做類似'(RETURN list_actions)'的事情? 我真的試過了,發生了一個錯誤: '*** - RETURN-FROM:沒有名爲NIL的塊當前可見「 – FriedRike

回答

1

的代碼可以更succintly表示如下:

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

哇!這麼小,它完美地工作!謝謝 – FriedRike

1

append需要兩個列表,不是列表和單個元素。在append中使用之前,您需要在對中加入一個清單。

目前這對是作爲列表的一部分,這使得列表不當,並導致第二個附加失敗,因爲不正確的列表不完全附加到結尾。

+0

我明白你的意思......你如何建議我在附件中使用它之前先列出一個列表? – FriedRike

+2

@FredericoNobredeCarvalho:'(list(cons n1 n2))',我會想象。 – Chuck

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