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

要素の決定

その他の動作に加え、if 式の else 部分は、キルリングに内容があり、かつ do-not-move の値が nil である場合に、kill-ring-yank-pointer の値を ARGth-kill-element に設定します。

コードはこんな感じです:

(nthcdr (mod (- n (length kill-ring-yank-pointer))
             (length kill-ring))
        kill-ring)))

これについては検証が必要です。ポインタを移動させない仕様でない限り、current-kill 関数は kill-ring-yank-pointer が指す先を変更します。(setq kill-ring-yank-pointer ARGth-kill-element)) 式が行っているのはまさにこの動作です。また、明らかに ARGth-kill-element は、前のセクションで説明されている nthcdr 関数を用いて、キルリング内の何らかの CDR と等しくなるように設定されています。(copy-region-as-kill を参照してください。)これはどのようにして実現されているのでしょうか。

これまで見てきたように(nthcdr参照)、nthcdr関数はリストのCDRを繰り返し取得することで動作します—CDRのCDRのCDRを取得し…

以下の2つの式は同じ結果になります。

(setq kill-ring-yank-pointer (cdr kill-ring))

(setq kill-ring-yank-pointer (nthcdr 1 kill-ring))

しかし、nthcdr 式はより複雑です。これは mod 関数を用いて、どの CDR を選択するかを決定します。

(まずは内部関数を確認することを忘れないでください。実際、modの内部まで踏み込む必要があります。)

mod 関数は、第1引数の値を第2引数で割った余りを返します。つまり、第1引数を第2引数で割ったときの余りを返します。返される値は、第2引数と同じ符号を持ちます。

したがって、

(mod 12 4)
  ⇒ 0  ;; because there is no remainder
(mod 13 4)
  ⇒ 1

この場合、第1引数は第2引数よりも小さいことが多いです。それで問題ありません。

(mod 0 4)
  ⇒ 0
(mod 1 4)
  ⇒ 1

- 関数がどのような動作をするかは推測できます。+ と同様ですが、加算ではなく減算を行います。- 関数は、第1引数から第2引数を減算します。また、length 関数がどのような動作をするかは既に分かっています(リストの長さを求める: length を参照)。これはリストの長さを返します。

また、nはcurrent-kill関数の必須引数の名前です。

したがって、nthcdr の第1引数が 0 の場合、nthcdr 式はリスト全体を返します。これは、以下を評価すれば分かります。

;; kill-ring-yank-pointer and kill-ring have a length of four
;; and (mod (- 0 4) 4) ⇒ 0
(nthcdr (mod (- 0 4) 4)
        '("fourth line of text"
          "third line"
          "second piece of text"
          "first some text"))

current-kill 関数の第1引数が 1 の場合、nthcdr 式は先頭要素を除いたリストを返します。

(nthcdr (mod (- 1 4) 4)
        '("fourth line of text"
          "third line"
          "second piece of text"
          "first some text"))

ちなみに、kill-ring と kill-ring-yank-pointer はどちらも グローバル変数 です。つまり、Emacs Lisp のあらゆる式からこれらにアクセスできます。これらは、let で設定されるローカル変数や、引数リスト内のシンボルとは異なります。ローカル変数は、それを定義する let 内、あるいは引数リストで指定する関数内(およびそれらから呼び出される式内)でしかアクセスできません。

(let 混乱の防止およびdefun マクロを参照。)