help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why is booleanp defined this way?


From: Pascal J. Bourguignon
Subject: Re: Why is booleanp defined this way?
Date: Fri, 17 Apr 2015 22:55:34 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Marcin Borkowski <address@hidden> writes:

> Hi all,
>
> this is what I found in subr.el:
>
> ,----
> | (defun booleanp (object)
> |   "Return t if OBJECT is one of the two canonical boolean values: t or nil.
> | Otherwise, return nil."
> |   (and (memq object '(nil t)) t))
> `----
>
> Seemingly, it doesn't make much sense: what is the purpose of saying
>
> (and (whatever) t)
>
> instead of just
>
> (whatever)
>
> for a predicate?  Of course, this "normalizes" any "truthy" value to
> "t", but is it really needed for anything (except perhaps being
> elegant)?

There's a difference between a boolean and a generalized boolean.
Also notice how the docstrings give the SPECIFICATION of the function:

    (defun booleanp (object)
       "Return t if OBJECT is one of the two canonical boolean values: t or nil.
    Otherwise, return nil."
       (and (memq object '(nil t)) t))

    (defun generalized-booleanp (object)
       "Return t if OBJECT is a generalized boolean, otherwise return nil"
       t) ; all the lisp objects are generalized booleans, by definition!

    (defun truep (generalized-boolean)
       "Return t if GENERALIZED-BOOLEAN is true, nil otherwise."
       (and generalized-boolean t))

    (defun falsep (generalized-boolean)
       "Return t if GENERALIZED-BOOLEAN is false, nil otherwise."
       (null generalized-boolean))

Obviously, the last three functions are idiotic, given that almost all the
boolean lisp operators actually take generalized boolean, and that there
is already NULL and NOT doing the same job as the last.


You don't write:

   (if (truep (member fruit '(apple banana)))
      'fruit
      'vegetable)

you write:

   (if (member fruit '(apple banana))
      'fruit
      'vegetable)




Also a little trick to obtain a boolean from a generalized boolean,
instead of (and … t), is to use the double negation: (not (not …)).
Arguably, not being a function it could be slower, but  a sufficiently
smart compiler should be able to generate the same code, or in the case
of emacs lisp virtual machine, produce actually shorter byte code, since
not is a virtual machine instruction:

(defun f (x) (and x t))
(disassemble (byte-compile 'f))
byte code:
  args: (x)
0       varref    x
1       goto-if-nil-else-pop 1
4       constant  t
5:1     return    

(defun g (x) (not (not x)))
(disassemble (byte-compile 'g))
byte code:
  args: (x)
0       varref    x
1       not       
2       not       
3       return    

But this is really nit-picking.

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


reply via email to

[Prev in Thread] Current Thread [Next in Thread]