GNU Info

Info Node: (emacs-lisp-intro.info)rotate-yk-ptr else-part

(emacs-lisp-intro.info)rotate-yk-ptr else-part


Next: Remainder Function Prev: Digression concerning error Up: rotate-yk-ptr body
Enter node , (file) or (file)node

The else-part of the `if' expression
....................................

   The else-part of the `if' expression is dedicated to setting the
value of `kill-ring-yank-pointer' when the kill ring has something in
it.  The code looks like this:

     (setq kill-ring-yank-pointer
           (nthcdr (% (+ arg
                         (- length
                            (length kill-ring-yank-pointer)))
                      length)
                   kill-ring)))))

   This needs some examination.  Clearly, `kill-ring-yank-pointer' is
being set to be equal to some CDR of the kill ring, using the `nthcdr'
function that is described in an earlier section.  (Note:
copy-region-as-kill.)  But exactly how does it do this?

   Before looking at the details of the code let's first consider the
purpose of the `rotate-yank-pointer' function.

   The `rotate-yank-pointer' function changes what
`kill-ring-yank-pointer' points to.  If `kill-ring-yank-pointer' starts
by pointing to the first element of a list, a call to
`rotate-yank-pointer' causes it to point to the second element; and if
`kill-ring-yank-pointer' points to the second element, a call to
`rotate-yank-pointer' causes it to point to the third element.  (And if
`rotate-yank-pointer' is given an argument greater than 1, it jumps the
pointer that many elements.)

   The `rotate-yank-pointer' function uses `setq' to reset what the
`kill-ring-yank-pointer' points to.  If `kill-ring-yank-pointer' points
to the first element of the kill ring, then, in the simplest case, the
`rotate-yank-pointer' function must cause it to point to the second
element.  Put another way, `kill-ring-yank-pointer' must be reset to
have a value equal to the CDR of the kill ring.

   That is, under these circumstances,

     (setq kill-ring-yank-pointer
        ("some text" "a different piece of text" "yet more text"))
     
     (setq kill-ring
        ("some text" "a different piece of text" "yet more text"))

the code should do this:

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

As a result, the `kill-ring-yank-pointer' will look like this:

     kill-ring-yank-pointer
          => ("a different piece of text" "yet more text"))

   The actual `setq' expression uses the `nthcdr' function to do the
job.

   As we have seen before (Note: nthcdr), the `nthcdr' function works
by repeatedly taking the CDR of a list--it takes the CDR of the CDR of
the CDR ...

   The two following expressions produce the same result:

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

   In the `rotate-yank-pointer' function, however, the first argument
to `nthcdr' is a rather complex looking expression with lots of
arithmetic inside of it:

     (% (+ arg
           (- length
              (length kill-ring-yank-pointer)))
        length)

   As usual, we need to look at the most deeply embedded expression
first and then work our way towards the light.

   The most deeply embedded expression is `(length
kill-ring-yank-pointer)'.  This finds the length of the current value of
the `kill-ring-yank-pointer'.  (Remember that the
`kill-ring-yank-pointer' is the name of a variable whose value is a
list.)

   The measurement of the length is inside the expression:

     (- length (length kill-ring-yank-pointer))

In this expression, the first `length' is the variable that was
assigned the length of the kill ring in the `let' statement at the
beginning of the function.  (One might think this function would be
clearer if the variable `length' were named `length-of-kill-ring'
instead; but if you look at the text of the whole function, you will
see that it is so short that naming this variable `length' is not a
bother, unless you are pulling the function apart into very tiny pieces
as we are doing here.)

   So the line `(- length (length kill-ring-yank-pointer))' tells the
difference between the length of the kill ring and the length of the
list whose name is `kill-ring-yank-pointer'.

   To see how all this fits into the `rotate-yank-pointer' function,
let's begin by analyzing the case where `kill-ring-yank-pointer' points
to the first element of the kill ring, just as `kill-ring' does, and
see what happens when `rotate-yank-pointer' is called with an argument
of 1.

   The variable `length' and the value of the expression `(length
kill-ring-yank-pointer)' will be the same since the variable `length'
is the length of the kill ring and the `kill-ring-yank-pointer' is
pointing to the whole kill ring.  Consequently, the value of

     (- length (length kill-ring-yank-pointer))

will be zero.  Since the value of `arg' will be 1, this will mean that
the value of the whole expression

     (+ arg (- length (length kill-ring-yank-pointer)))

will be 1.

   Consequently, the argument to `nthcdr' will be found as the result of
the expression

     (% 1 length)


automatically generated by info2www version 1.2.2.9