Subject: bug#33998: 27.0.50; cl-delete does not delete the first list element

From: João Távora <[email-masked]>
Date: Mon, 07 Jan 2019 21:06:44 +0000

Dmitry Gutov <[email-masked]> writes:

> On 07.01.2019 23:20, Deus Max wrote:
>> The variable you pass is modified.
>
> The value. Not the variable. The latter keeps pointing at whatever
> cons it's pointed before.

What Dmitry said, let me just add this: what you call variables in Lisp
are actually symbols that, among other things, may (or may not) have a
"variable binding" (this is why you sometimes get "unbound" errors when
you try to evaluate a symbol's variable value).  They are indeed
pointers.

So if you read "destructive" as in "modify a variable's binding,
i.e. the place where it points to" then no *function* can do that when
passed the variable, because what it is receiving is the value pointed
to by the symbol.  A macro, like 'setq' or 'pop' can do that, because it
"sees" the symbol.

An alternative place to read on Common Lisp's DELETE is Common Lisp's
hyperspec:

   http://www.lispworks.com/documentation/HyperSpec/Body/f_rm_rm.htm

The "may modify sequence" sentence figures prominently there.

Emacs's cl-delete attempts to emulate Common Lisp's CL:DELETE.  In Emacs
it behaves, in this regard, no different from delete or delq.  It is
"potentially destructive" because it *may* modify the *structure* of the
sequence *value* that you pass to it, be it a linked list or a vector:

1) If it is a linked list, it does the trick of making the pointer
   before the element you want to delete point to the element after it;

2) If it is a vector, it moves all the vector elements after the one you
   want to delete back one position and readjusts the vector size.

If you notice, for situation 2 you could theoretically affect the
variable binding directly.  And curiously, this is where I found
differences between Emacs's cl-delete and some CL's implementation of
CL:DELETE.

Emacs:

    (setq bla (vector 1 2 3 4))
    (delete 1 bla) => [2 3 4]
    bla => [1 2 3 4]
     
    (setq bla (vector 1 2 3 4))
    (cl-delete 1 bla) => [2 3 4]
    bla => [1 2 3 4]

Allegro common lisp and CMU common lisp:

   (setq bla (vector 1 2 3 4))
   (delete 1 bla) => #(2 3 4) 
   bla => #(2 3 4)

SBCL common lisp:

   (setq bla (vector 1 2 3 4))
   (delete 1 bla) => #(2 3 4)
   bla => #(2 3 4 4)

So, for vector sequences, CL:DELETE is apparently allowed to do
whatever.  Reading the hyperspec, it seems that all these results are
correct, even SBCL's.

João