2017-03-10 90 views
1

我寫了複製在列表中的項目如下功能double()是否可以限制在duplicate()函數中調用cons函數的次數?

(defun duplicate (l) 
    (if (null l) nil 
     (cons (car l) (cons (car l) (duplicate (cdr l)))))) 

duplicate()功能做出兩次調用CONS功能爲每個項目在列表中:

Break 1 [2]> (trace cons) 
;; Traçage de la fonction CONS. 
(CONS) 

Break 1 [2]> (duplicate '(1 2 3)) 
1. Trace: (CONS '3 'NIL) 
1. Trace: CONS ==> (3) 
1. Trace: (CONS '3 '(3)) 
1. Trace: CONS ==> (3 3) 
1. Trace: (CONS '2 '(3 3)) 
1. Trace: CONS ==> (2 3 3) 
1. Trace: (CONS '2 '(2 3 3)) 
1. Trace: CONS ==> (2 2 3 3) 
1. Trace: (CONS '1 '(2 2 3 3)) 
1. Trace: CONS ==> (1 2 2 3 3) 
1. Trace: (CONS '1 '(1 2 2 3 3)) 
1. Trace: CONS ==> (1 1 2 2 3 3) 
(1 1 2 2 3 3) 

是它可能將每個列表項目的呼叫次數限制爲CONS

+1

歸根結底,沒有,因爲'cons'只增加一個項目名單,並且在每一步添加兩個項目。 – chepner

+0

我們不能將'cons'函數與lisp映射函數結合起來解決這個問題嗎? – lukas

+0

我認爲這取決於你的實現是否有任何優化連接兩個列表。在概念上(我認爲),任何構建新列表的任何事都可以通過將一個元素一次添加到任意長列表的前面來完成。 – chepner

回答

1

不,由於相同的原因,您不能使用5升水填充10升桶。

10個元素的列表需要10個cons單元。

+0

謝謝你的幫助。您的評論確認我的意見 – lukas

0

破壞性的版本將使其成爲可能:

(defun duplicate (l) 
    (if (null l) 
     nil 
    (destructuring-bind (f . r) 
     l 
     (setf (cdr l) 
      (cons f (duplicate r))) 
     l))) 

CL-USER 10 > (duplicate (list 1 2 3 4 5)) 
(1 1 2 2 3 3 4 4 5 5) 
0

可以消除所有的利弊呼籲:

(list* (car l) (car l) (duplicate (cdr l)))

+0

您如何確定在任何Common Lisp實現中'list *'不會調用'cons'? – Sylwester

+0

在某種程度上,我一直很face,,但我也認爲OP可能更希望能夠避免*編碼*兩個cons調用,因此提供了更好的'list *'語法。但回過頭來看,我發現「痕跡」被視爲真相的源泉,所以我的水晶球可能會讓我失望。 – kennytilton

相關問題