This is something fairly obvious to every seasoned Lisp programmer, but let’s not forget that there are novices, too.

Many Elisp functions are noted to be “destructive”, which means that they can change their arguments. For instance, if you want to sort a list, you may use the `sort`

function, which is said to modify its argument by side effects (this is exactly what “destructive” means). This does not necessarily mean, however, that after executing ```
(sort
some-list)
```

, the variable `some-list`

will magically contain a sorted version of it previous self! Let’s consider two examples.

(setq some-list '(1 3 2)) (sort some-list #'<) some-list

After evaluating the above code, `some-list`

is bound to `(1 2 3)`

, i.e., the sorted version, and hence you might think that this is always going to be the case.

Wrong.

Let’s look at this code.

(setq some-list '(3 1 2)) (sort some-list #'<) some-list

See? Now `some-list`

is just `(3)`

.

What is going on here?

Well, in order to understand what happens, we will use the famous cons cell diagrams, found in so many books on Lisp.

Remember that each cons cell contains two “slots”: *car* and *cdr*. A list is simply a chain of cons cells whose cars contain (more precisely: point to) values held in the list, and cdrs point to the next cons cell in the chain.

Hence, the list in our first example looks like this.

some-list | V +-A---+-----+ +-B---+-----+ +-C---+-----+ | 1 | ------>| 3 | ------>| 2 | | +-----+-----+ +-----+-----+ +-----+-----+

(An empty slot means nil, of course.)

After the first sort, cons cell A’s cdr is modified to point at C, C’s cdr points at B, and B’s cdr is set to nil. Since `some-list`

still points to A (as we did not assign anything else to this variable), our list looks like this:

some-list | +-------------------------+ | | | V | V +-A---+--|--+ +-B---+-----+ +-C---+-----+ | 1 | | | | 3 | | | 2 | | | +-----+-----+ +-----+-----+ +-----+--|--+ ^ | | | +----------------------+

Let’s consider now the second example. We start with this:

some-list | V +-A---+-----+ +-B---+-----+ +-C---+-----+ | 3 | ------>| 1 | ------>| 2 | | +-----+-----+ +-----+-----+ +-----+-----+

and after sorting, our cons cells look like this:

some-list | | +-------------------------------+ | | | V V | +-A---+-----+ +-B---+-----+ +-C---+--|--+ | 3 | | | 1 | ------>| 2 | | | +-----+-----+ +-----+-----+ +-----+-----+

See what happened? Since `some-list`

points at A now, and A’s cdr is nil, we get `(3)`

as `some-list`

.

So, what we should do about it? It turns out that `sort`

returns “the sorted sequence”, which means cons cell B. Therefore, if we want `some-list`

to be sorted, we should say this instead.

(setq some-list '(3 1 2)) (setq some-list (sort some-list #'<)) some-list

And of course, the same goes for other destructive functions, like `nreverse`

or `cl-delete`

.

(You might also look at my earlier post about destructive functions and comments to that post.)