2013-04-02 37 views
2

我遇到了代碼輸出的問題,我想是在檢查列表中null的條件時。在Lisp中不使用mapcar將列表中的數字乘以數字(座標方式)

我想完成的問題是:編寫一個函數vecmul,它將輸入兩個簡單的數字列表。 vecmul應該乘以這些列表座標明智,因爲你會乘以向量。假設兩個列表長度相同。 [例如,(vecmul '(2 3 4 5) '(1 4 5 2))返回(2*1 3*4 4*5 5*2)(2 12 20 10)。您不允許使用mapcar此功能]

到目前爲止,我有

(defun vecmul (list list2) 
    (cond ((null list) 0) 
    (t (cons (* (car list) (car list2)) 
       (vecmul (cdr list) (cdr list2)))))) 

[170]> (setq l '(2 4 6)) 
(2 4 6) 
[171]> (setq r '(1 3 5)) 
(1 3 5) 
[172]> (vecmul l r) 
(2 12 30 . 0) 

我得到正確的數字,它只是列表中添加「」和列表末尾的「0」。我非常肯定這是因爲我沒有停止遞歸權或者沒有正確使用cond。我只是不完全確定如何糾正它。

回答

4

你已經明白了。但是,當正確終止爲nil時,您將以0終止您的列表。此代碼的工作:

(defun vecmul (list list2) 
    (cond ((null list) nil) 
    (t (cons (* (car list) (car list2)) (vecmul (cdr list) (cdr list2)))))) 

當你調用(cons 1 2),利弊細胞你寫(1 . 2)。標記(1 2 3 4 5)只是(1 . (2 . (3 . (4 . (5 . nil)))))的簡寫。如果最後一個cons單元的cdr6而不是nil,那麼您會得到(1 . (2 . (3 . (4 . (5 . 6))))),這會縮短爲(1 2 3 4 5 . 6)

4

Neil Forrester回答了你的問題。

還有一些言論。在Lisp中使用現代名稱:firstrest

(defun vecmul (list1 list2) 
    (cond ((null list1) nil) 
     (t (cons (* (first list1) (first list2)) 
       (vecmul (rest list1) (rest list2)))))) 

如果你有一個簡單的真假決定,IF可能會更好。由於涉及到列表操作,因此我會將其編寫爲以下內容,而不是使用WHEN

(defun vecmul (list1 list2) 
    (if (null list1) 
     nil 
    (cons (* (first list1) (first list2)) 
      (vecmul (rest list1) (rest list2))))) 

最佳使用在真實代碼一個循環結構或映射。如上所述,遞歸具有堆棧深度限制。循環沒有這個限制。

(defun vecmul (list1 list2) 
    (loop for e1 in list1 and e2 in list2 
     collect (* e1 e2))) 

(defun vecmul (list1 list2) 
    (mapcar #'* list1 list2)) 
相關問題