2017-03-10 14 views
1

私は次のようにリスト内の項目を複製機能double()を書いた:duplicate()関数のcons関数の呼び出し回数を制限することはできますか?

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

duplicate()関数は、リスト内の各項目についてCONS機能には、2つの呼び出しを行う:

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つに制限できますか?

+1

最終的には、いや、 'cons'は、リストに項目を1つだけ追加されますので、各ステップで2つのアイテムを追加しています。 – chepner

+0

そして、これを解決するために 'cons'関数とLispマッピング関数を組み合わせることはできませんか? – lukas

+0

私はあなたの実装が2つのリストを連結するための最適化を持っているかどうかにかかっていると思います。概念的には(私は思うが)、新しいリストを作成するものは、任意の長いリストの先頭に一度に1つの要素を追加することによってそうする。 – chepner

答えて

1

同じ理由で、5リットルの水を使用して10リットルのバケツを充填することはできません。

10個の要素のリストには10​​個のコンスセルが必要です。

+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

'list *'はCommon Lispのどの実装でも 'cons'を呼び出さないでしょうか? – Sylwester

+0

ある程度私は面白かったですが、OPは2つの短所をコーディングするのを避ける方法を探していた可能性も考えました。しかし、私のクリスタルボールが私に失敗する可能性があるので、私は戻って振り返ると、 "トレース"は真実のソースとして撮影されて参照してください。 – kennytilton

関連する問題