Common Lisp で最後の要素のないリストを返すばかげた関数を書きました。この問題に対するよりエレガントな解決策はありますか?
これが私のコードです:
(defun list-without-last (l)
(if (> (length (rest l)) 0)
(append (list (first l)) (list-without-last (rest l)))
nil))
Common Lisp で最後の要素のないリストを返すばかげた関数を書きました。この問題に対するよりエレガントな解決策はありますか?
これが私のコードです:
(defun list-without-last (l)
(if (> (length (rest l)) 0)
(append (list (first l)) (list-without-last (rest l)))
nil))
Lisp のように、短くてシンプルです。ここに魔法のものがあります:
(defun without-last(l)
(reverse (cdr (reverse l)))
)
関数には 2 つの問題があります。
あなたはLENGTHを使用しています。LENGTH はリスト全体をスキャンする必要があります。
APPEND を使用しています。CONSを使用してみてください。短所はより簡単です。
Common Lisp もすでにこの機能を提供しています。それはBUTLASTと呼ばれています。
実際のコードでは、再帰も使用しません。スタック サイズによって、処理できるリストの長さが制限されます。
LOOP
マクロを使用した反復バージョン:
CL-USER> (defun my-butlast (list)
(loop for l on list
while (rest l)
collect (first l)))
MY-BUTLAST
CL-USER> (compile 'my-butlast)
MY-BUTLAST
NIL
NIL
CL-USER> (my-butlast '(1 2 3 4 5))
(1 2 3 4)
CL-USER> (my-butlast '(1))
NIL
CL-USER> (my-butlast '(1 2))
(1)
コピーを作成するのではなく、その場でリストを変更する必要がある場合があります。その場合、これが便利な場合があります。
(defun butlast! (x)
(do ((y x (cdr y)))
((null (cddr y))
(and (rplacd y nil) (return x)))))