その他の動作に加え、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
内、あるいは引数リストで指定する関数内(およびそれらから呼び出される式内)でしかアクセスできません。