Subject: bug#33036: Bug with the procedure nil? inside a specific code

From: Mark H Weaver <[email-masked]>
Date: Sat, 13 Oct 2018 21:11:44 -0400

Hi,

calcium <[email-masked]> writes:
> The procedure nil? is not listed in the procedure index :
> https://www.gnu.org/software/guile/docs/docs-2.0/guile-ref/Procedure-Index.html

The link above is the manual for Guile 2.0, which didn't have 'nil?'.
It was added in Guile 2.2.

> There is a page that speak about nil :
> https://www.gnu.org/software/guile/manual/html_node/Nil.html
> However it doesn’t mention the nil? Procedure
>
> The only documentation that I found about nil? is this one :
>
> (procedure-documentation nil?)
> => "- Scheme Procedure: nil? x\n     Return `#t' iff X is nil, else
> return `#f'."

I agree that the documentation for 'nil?' is woefully inadequate.  We
should add a manual entry for 'nil?' and improve its docstring.

'nil?' tests whether Emacs Lisp code would consider the value to be nil,
i.e. whether it would be considered false by Elisp 'if' or 'cond'.

Scheme has two distinct values for the empty list () and false #f.  In
Elisp, both of these concepts are represented by the same value: nil.
As a result, the empty list is considered "true" in Scheme, and "false"
in Elisp.

In other words, 'nil?' returns #t if its argument is #f, (), or #nil,
otherwise it returns #f.

> (procedure-documentation null?)
> => "- Scheme Procedure: null? x\n     Return `#t' iff X is the empty
> list, else `#f'."
>
> The procedure documentation is not the same for nil? and null?
> They seem nonetheless to be the same.

No, they differ in their handling of #f:

  (null? #f) => #f
  (nil?  #f) => #t

> Here is the bug that I found :
>
> ;;; -START- code with the bug -START- ;;;
>
> (define (strange lst)
>   (let loop ((lst lst)
>              (is-empty '()))
>     (cond ((nil? lst)
>            (if (nil? is-empty) 'works
>              (list 'should-not-occur is-empty)))
>           (else
>            (loop (cdr lst)
>                  is-empty)))))
>
> (strange '())
> => (should-not-occur ())
>
> (strange #nil)
> => (should-not-occur ())

Indeed, this certainly indicates a bug.

I believe the bug is in 'local-type-fold' in (language cps type-fold).
It contains a local procedure 'scalar-value' which, if I understand
correctly, seems to incorrectly assume that (nil? x) returns #t if and
only if X is 'eq?' to #nil.

To be continued...

Thanks very much for this detailed report!

    Regards,
      Mark