Search code examples
listemacselispcdr

why the change is in place for the list with elisp?


I have a question about elisp. For example:

(setq trees '(maple oak pine birch))
      -> (maple oak pine birch)
(setcdr (nthcdr 2 trees) nil)
      -> nil
trees
      -> (maple oak pine)

I thought (nthcdr 2 trees) returns a new list - (pine birch) and put the list into the setcdr expression, which should not change the value of trees. Could anyone explain it to me?


Solution

  • If you read the documentation string for nthcdr, you'll see that it just returns a pointer to the "nth" "cdr" - which is a pointer into the original list. So you're modifying the original list.

    Doc string:

    Take cdr N times on LIST, return the result.
    

    Edit Wow, "pointer" seems to stir up confusion. Yes, Lisp has pointers.

    Just look at the box diagrams used to explain list structure in lisp (here's Emacs's documentation on that very thing):

         --- ---      --- ---      --- ---
        |   |   |--> |   |   |--> |   |   |--> nil
         --- ---      --- ---      --- ---
          |            |            |
          |            |            |
           --> rose     --> violet   --> buttercup
    

    Look at all those arrows, they almost look like they're .... pointing to things. When you take the cdr of a list, you get what the 2nd box refers to (aka "points" to), be it an atom, a string, or another cons cell. Heck, check it out on Wikipedia's entry for CAR and CDR.

    If it feels better to call it a reference, use that terminology.

    cdr certainly does NOT return a copy of what it refers to, which is what was confusing RNAer.