There is a fun story about booleans in Emacs Lisp - there are no booleans in Emacs Lisp. Sort of. Because we have a symbol
nil, which means an empty list. You can write it as
() - they both stand for the same object, the symbol
Since LISP is all about list processing, empty list is something very
false that we don’t have special symbol for
false values, as empty list serves this purpose well.
Everything that is not an empty list has a meaning of
true. However, there is a symbol
t which is the preferred way to represent the truth value
t are considered canonical boolean values. There is a function
booleanp that returns
t if the argument is a canonical boolean value and
The fun begins when you need to check if two boolean values are equal. Since non-nil (or not an empty list) can mean many different things (like
the only true editor") you can’t just do regular equality check.
There are, however, several tricks to get it working. The most obvious solution is to convert value to a canonical boolean value.
We can directly use
(if "Some truth" t nil) ; => t (if 42 t nil) ; => t (if t t nil) ; => t (if nil t nil) ; => nil (let ((a t) (b "Emacs is the only true editor")) (equal (if a t nil) (if b t nil))) ; => t (defun boolean-eq (a b) (equal (if a t nil) (if b t nil))) (let ((a t) (b "Emacs is the only true editor")) (boolean-eq a b)) ; => t
if is a little bit cumbersome, but when we hide it inside of a helper function it’s not that bad, actually.
The same result can be achieved by using
(when "Some truth" t) ; => t (when 42 t) ; => t (when t t) ; => t (when nil t) ; => nil (let ((a t) (b "Emacs is the only true editor")) (equal (when a t) (when b t))) ; => t (defun boolean-eq (a b) (equal (when a t) (when b t))) (let ((a t) (b "Emacs is the only true editor")) (boolean-eq a b)) ; => t
There is another function we can use -
not, which returns
t if the argument is
nil, and returns
nil otherwise. Yes, it negates the value, but the result is one of the canonical booleans, so we are good.
Since a ≡ b is equivalent to ¬a ≡ ¬b, we can just compare negated values.
|a||b||¬a||¬b||a ≡ b||¬a ≡ ¬b|
This one looks a little bit better when used without a helper function, at least in my opinion.
Sometimes you want to do something when two ‘boolean’ values are not equal.
For such situations, there is a
xor function, which returns
nil when both arguments are equal in the canonical boolean form and
(xor nil nil) ; => nil (xor nil t) ; => t (xor t nil) ; => t (xor t t) ; => nil (xor "Some truth" nil) ; => t (xor "Some truth" t) ; => nil (xor 42 nil) ; => t (xor 42 t) ; => nil (let ((a nil) (b "Emacs is the only true editor")) (when (xor a b) (message "Some real work begins"))) ; => Some real work begins
Other functions (like
and) also convert values to canonical boolean values. So you can keep it in mind.
The sole purpose of this post is fun. If you didn’t get your portion of fun, then it’s not funny at all. Please fix it somehow.