GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html ・ emacs-doc.conao3.com

5.6.3 リストを並べ替える関数

以下に、構成要素であるコンスセルのCDRを変更することで、リストを破壊的に再構成する関数をいくつか紹介します。これらの関数が破壊的なのは、引数として渡された元のリストを消費し、コンスセルを再リンクして、戻り値となる新しいリストを構築するためです。

コンスセルを変更する別の関数については、リストを集合として使用するのdelqを参照してください。

関数: nconc &rest lists

This function returns a list containing all the elements of lists. Unlike append (see Building Cons Cells and Lists), the lists are not copied. Instead, the last CDR of each of the lists is changed to refer to the following list. The last of the lists is not altered. For example:

(setq x (list 1 2 3))
     ⇒ (1 2 3)
(nconc x '(4 5))
     ⇒ (1 2 3 4 5)
x
     ⇒ (1 2 3 4 5)

nconc の最後の引数自体は修飾されないため、上記の例のように '(4 5) のような定数リストを用いるのが妥当です。同様の理由から、最後の引数は必ずしもリストである必要はありません:

(setq x (list 1 2 3))
     ⇒ (1 2 3)
(nconc x 'z)
     ⇒ (1 2 3 . z)
x
     ⇒ (1 2 3 . z)

ただし、その他の引数(最後の一つを除く)は可変リストである必要があります。これらはドット付きリストとすることができ、その最後のCDRを次の引数で置き換えます:

(nconc (cons 1 2) (cons 3 (cons 4 5)) 'z)
     ⇒ (1 3 4 . z)

よくある落とし穴は、定数リストを nconc の最後以外の引数として使用することです。このようにすると、結果として生じる動作は未定義となります(自己評価形式を参照)。プログラムを実行するたびに内容が変わってしまう可能性があります!起こり得るのは次のようなことです(ただし、必ず起こるとは限りません):

(defun add-foo (x)            ; We want this function to add
  (nconc '(foo) x))           ;   foo to the front of its arg.

(symbol-function 'add-foo)
     ⇒ #f(lambda (x) [t] (nconc '(foo) x))

(setq xx (add-foo '(1 2)))    ; It seems to work.
     ⇒ (foo 1 2)
(setq xy (add-foo '(3 4)))    ; What happened?
     ⇒ (foo 1 2 3 4)
(eq xx xy)
     ⇒ t

(symbol-function 'add-foo)
     ⇒ #f(lambda (x) [t] (nconc '(foo 1 2 3 4) x))