2

Emacs Lisp マニュアルには、関数 nconc について次のように記載されています。

nconc の最後の引数自体は変更されないため、上記の例のように '(4 5) などの定数リストを使用するのが合理的です。同じ理由で、最後の引数はリストである必要はありません

そして確かに私は書くことができます

(setq x '(1 2 3))
=> (1 2 3)

(nconc x 0)
=> (1 2 3 . 0)

しかし、それは完全に壊れたリストをもたらします:

(length x)
=> eval: Wrong type argument: listp, 0

(butlast x)
=> butlast: Wrong type argument: listp, 0
  • 元のリストを取得するにはどうすればよいですか? (reverse (cdr (reverse '(1 2 3 . 0))))それも切らない。
  • これはどのコンテキストで有用なパターンですか? 標準ディストリビューションminibuffer.elでは、特に、いくつかの機能が使用されていcompletion-all-completionsます。
4

3 に答える 3

5

それらは「壊れた」リストではありません。それらは実際には不適切なリストとして知られています (適切なnilリストである -terminated リストとは対照的に)。先ほど名前を付けたやなどの多くのリスト関数は、適切なリストを想定し、適切なリストに対してのみ true を返します。lengthbutlastlistp

不適切なリストは連想リストで使用されます (連想リスト自体は適切でなければならないにもかかわらず、連想が適切でないことがよくあります)。


不適切なリストを適切なものにしたい場合は、次の 2 つのオプションがあります。

  • 「不適切」な要素を削除します。
  • 不適切な要素を適切なリストの最後の要素として扱います。

properise前者を実行する、私が作成したプロシージャを次に示します。

(defun properise (x)
  (let ((r nil))
    (while (consp x)
      (push (pop x) r))
    (nreverse r)))

(後者の動作が必要な場合は(unless (null x) (push x r))、行の直前に追加してnreverseください。)

于 2015-02-18T00:23:29.900 に答える
2

一般的に、最後の要素が cdr に NIL 以外のオブジェクトを持つコンスセルであるようなデータ構造を作成することは避けます...デバッグが難しくなり、ハックであり、コードが理解しにくくなります...

于 2015-02-18T05:32:53.720 に答える
0

なぜこれが良いパターンなのかはまだわかりませんが、コピーを作成せずに、不適切なリストから適切なリストを取得する簡単な方法を次に示します。

(defun nmake-proper-list (x)
  (let ((y (last x)))
    (setcdr y nil)
    x))
于 2015-02-18T13:42:22.657 に答える