Subject: Re: bug#62037: (proper-list-p '#1=(a #1#)) => 2. It should return nil.

From: Ruijie Yu <[email-masked]>
Date: Wed, 08 Mar 2023 12:13:50 +0800

Notice the distinction between these two snippets:

    (let ((lst-1 '#1=(a #1#)))
      (list lst-1 (proper-list-p lst-1)))
    ;; => ((a #1) 2)

    (let ((lst-2 '#1=(a . #1#)))
      (list lst-2 (proper-list-p lst-2)))
    ;; => ((a . #0) nil)

Apparently, at least from the current behaviors, lst-1 is considered a
"proper list" because it is not a *circular list* [1], but still a
*circular object* [2].  This is because, in
essense, this is a list of two elements,
where the first one is 'a, and the second one is lst-1 itself.
Rewriting lst-1, we see that lst-1 is also not considered as dotted.

    (setq lst-1 '#1=(a #1# . nil))

That said, given that the docstring has some ambiguities on what
"circular" means -- as in, whether it means "circular list" or "circular
object", maybe at least the docstring and the Elisp manual about
`proper-list-p' should be updated to clarify which one it means?  Then
the implementation of `proper-list-p' can follow suite if necessary.

[1]:
(info "(elisp) Cons Cells")

> If the CDR of a list’s last cons cell is some value other than ‘nil’,
> we call the structure a “dotted list”, since its printed
> representation would use dotted pair notation (*note Dotted Pair
> Notation::).  There is one other possibility: some cons cell’s CDR
> could point to one of the previous cons cells in the list.  We call
> that structure a “circular list”.

[2]:
(info "(elisp) Circular Objects")

> To represent shared or circular structures within a complex of Lisp
> objects, you can use the reader constructs ‘#N=’ and ‘#N#’.

--
Best,

RY