I know that nil
is a constant so its value cell cannot be changed,
but why its function cell cannot be set as well?
ELISP> (defun t ())
t
ELISP> (defun nil ())
*** Eval error *** Cannot define ‘nil’ as a function
I know that nil
is a constant so its value cell cannot be changed,
but why its function cell cannot be set as well?
ELISP> (defun t ())
t
ELISP> (defun nil ())
*** Eval error *** Cannot define ‘nil’ as a function
From a language design point of view, Emacs Lisp accepts nil
as a parameter to functions to mean “do nothing” or “do some sensible default” or “turn it off” in a lot of contexts. Being able to assign a value or a function to nil
could be very confusing. For example, (fset 'func nil)
is equivalent to (fmakunbound 'func)
— but if nil
could be a valid function after running (fset nil 'nil-func)
, then (fset 'func nil)
should be equivalent to (defalias 'func 'nil-func)
. So which of the two wins? Or should (fset nil 'nil-func)
cause every undefined function to run nil-func
?
Until and including Emacs 25.x, you could set the function cell of nil
, leading to weirdness such as what I posted above. This was reported as bug #25110: actually calling nil
as a function didn't work. The bug was fixed in Emacs 26.0 by forbidding to set the function cell of nil
.
It's arguably a documentation bug that this doesn't seem to be mentioned in the manual (presumably where it discusses constants). But that's a very minor omission, since defining nil
as a function isn't something one would naturally want to do, given that it doesn't have clearly-defined behavior.
That's hard-coded:
(defmacro defun (name arglist &rest body)
"..."
(declare (doc-string 3) (indent 2))
(or name (error "Cannot define '%s' as a function" name))
...)
I'd suggest it would be rather unwise to define a nil
function, and this protection prevents it from happening accidentally, so that seems sensible to me.
I note that you can't do it by bypassing defun
either, as fset
also guards against this. Evidentially not everyone agrees that it's worth the CPU cycles to protect people against doing this, but this is how things are at present:
if (NILP (symbol) && !NILP (definition))
/* There are so many other ways to shoot oneself in the foot, I don't
think this one little sanity check is worth its cost, but anyway. */
xsignal1 (Qsetting_constant, symbol);