Subject: bug#7086: `booleanp' return value is multi-valued list

From: MON KEY <[email-masked]>
Date: Fri, 24 Sep 2010 02:41:43 -0400

On Thu, Sep 23, 2010 at 4:12 AM, Eli Zaretskii <[email-masked]> wrote:
>
> The precise form of the return value is an implementation detail.
> Such details need not be documented.
>
> Are there any _real-life_ use cases where this matter?
>
Probably none in the life of an Emacs devel. Though down here
in the reified mud of consequence when Emacs prompts
that some file variable doesn't satisfy booleanp it would
be nice to know that the predicate was homoiconic. Whatever.

(info "(elisp)File Local Variables")

,----
|    You can specify safe values for a variable with a
| `safe-local-variable' property.  The property has to be a function of
| one argument; any value is safe if the function returns non-`nil' given
| that value.  Many commonly-encountered file variables have
| `safe-local-variable' properties; these include `fill-column',
| `fill-prefix', and `indent-tabs-mode'.  For boolean-valued variables
| that are safe, use `booleanp' as the property value.  Lambda
| expressions should be quoted so that `describe-variable' can display
| the predicate.
`----

>
> Implementation details don't need to be documented, unless they really
> matter to Lisp programs which use these APIs.
>

This one matters. It is the penultimate Emacs lisp predicate.
It tests for a boolean value yet it returns a list.

>
> Please explain what is  missing, exactly.
>

I did. The return values should be either one of:

 t | nil

 or  (my preference):

(t t) | (nil t)

Returning two different length lists for a predicate that interrogates a boolean
is ill conceived.

>
> Again, why is it important?
>

How can it not be?

>> Also, there is this goofiness:
>>
>> (defun tt--bool-w/opt (&optional x)
>>   (booleanp x))
>>
>> (tt--bool-w/opt nil) ;=> (nil t)
>> (tt--bool-w/opt t)   ;=> (t)
>> (tt--bool-w/opt)     ;=> (nil t)
>
> See (info "(elisp)Argument List") for an instant enlightening: omitted
> optional arguments default to nil.
>

Oh, now I get it.

- Omitted optional arguments default to nil;
- and nil evaluates to itself;
- the empty list is identical to nil;
- and interrogating the constant with a predicate returns a list...
- of length (length (booleanp nil)) => 2
- unless its of length (length (booleanp t)) => 1

Yep, crystal clear.

>> (defun tt--bool (x)
>>   (booleanp x))

> {...}

> Exactly!  See the above node in the manual.
>
> But this has nothing to do with booleanp.

It has everything to do with it.
These are just the types of situations where interrogating a boolean is what is
wanted.

>
> Emacs gives you enough rope to hang yourself; don't do that, unless
> you mean it.
>
Its a horrible metaphor. That's not rope its Emacs' leash which it
drags along so
someone can always drag it back out of the mire:

(defun booleanp (object)
  (or (and (eq object t) '(t t))
      (and (eq object nil) '(nil t))))

(booleanp "bubba")
;=> nil

(booleanp t)
;=> (t t)

(booleanp nil)
;=> (nil t)

(booleanp ())
;=> (nil t)