2017-09-10 57 views
-1

我對LISP很陌生,我試圖在類的cond語句上工作。目前,我試圖檢查傳遞的值是否是列表,如果是,請將字母d附加到列表中。LISP列表沒有追加和打印兩次

這裏是我的代碼:

(defun test(L) 
(listp L) 
(cond ((listp L) (append L (list 'd))) 
) 
(write L) 
) 
(test (list 'a 'b 'c)) 

我得到的輸出是:

(A B C) 

(A B C) 

如果我改變了測試:(test (car(list 'a 'b 'c)))

新的輸出我得到的是:

A 

A 

我想知道的兩件事是

1)如果第一次測試通過列表,爲什麼不把D附加到列表上?

2.)爲什麼要打印兩次?我正在使用LISP Works,所以我認爲它實際上就是它總是輸出最終值或某物的東西。

+1

請你修復碼f ormatting? – sds

回答

3

1.)相同的原因str + "d"不改變Java或Python中的str。它會創建一個你不使用的新列表!

>>> str + "d" 
'abcd' 
>>> str 
'abc' 

瘋狂的類似是不是?

2.)在CL中,return是最後一次評估的表達式。 REPL將每個頂級表達式結果打印到終端。 Python做這個太:

>>> def test(): 
... x = 2 + 3 
... print x 
... return x 
... 
>>> test() 
5 
5 

更新

如何變異的參數列表。簡單的答案是,你需要變異最後一對的參數,而不是:

(defun test (l) 
    (assert (consp 1) (l) "l needs to be a non nil list. Got: ~a" l) 
    (nconc l (list 'd) 
    (write l))) 

(defparameter *test1* (list 1 2 3)) 
(defparameter *test1-copy* *test1*) 
(test *test1*)   ; ==> (1 2 3 d) (and prints (1 2 3 d)) 
*test1*     ; ==> (1 2 3 d) 
*test1-copy*    ; ==> (1 2 3 d) 
(eq *test1* *test1-copy*) ; ==> t 

(test '()) 
** error l needs to be a non nil list. Got: NIL 

(nconc l x)確實(setf (cdr (last l)) x)

如果您需要更改綁定,那麼你需要做一個宏:

(defmacro testm (var) 
    (assert (symbolp var) (var) "List needs to be a variable binding. Got: ~a" var) 
    `(progn 
    (when (listp ,var) 
     (setf ,var (append ,var (list 'd))) 
    (write ,var)))) 

(macroexpand '(testm *test2*)) 
; ==> (progn 
;  (when (consp *test2*) 
;   (setf *test2* (append *test2* (list 'd)))) 
;  (write *test2*)) 

(defparameter *test2* (list 1 2 3)) 
(defparameter *test2-copy* *test2*) 
(testm *test2*)   ; ==> (1 2 3 d) (and prints (1 2 3 d)) 
*test2*     ; ==> (1 2 3 d) 
*test2-copy*    ; ==> (1 2 3) 
(eq *test2* *test2-copy*) ; ==> nil 

(defparameter *x* nil) 
(testm *x*)    ; ==> (d) (and prints (d)) 
*x*      ; ==> (d) 

(testm '(1)) 
** error List needs to be a variable binding. Got: '(1) 

慣用的方式來做到這一點

(defun test (list) 
    (if (consp list) 
     (append list '(d)) 
     list)) 

(write (test '(1 2 3))) 
; ==> (1 2 3 d) (and prints (1 2 3 d)) 

(defparameter *test3* '(1 2 3)) 
(setf *test3* (test *test3*)) 
*test3* ; ==> (1 2 3 d) 
+0

有什麼最好的方式讓L被更新並寫出L? –

+1

@KyleJ更新瞭如何改變以及如何更好地做到這一點。 – Sylwester

+0

非常感謝你 –