Weird Emacs: Listy Lambdas
I guess everyone who has spent any time with Emacs Lisp, knows that the language is full of oddities and quirks. That’s often a source of frustration for people coming from other languages, but it’s part of Emacs’s charm. Even after 15 years with Emacs and working on numerous Emacs packages, I still find things that manage to surprise me in Emacs Lisp. Consider the following:
(functionp (lambda (x) "I don't do much")) ;; => t
(functionp '(1 2 3)) ;; => nil
(listp (lambda (x) "I don't do much")) ;; => t
(listp '(1 2 3)) ;; => t
Turns out lambdas are both functions and lists! Weird, right?
I learned this yesterday, when someone reported a bug in Projectile triggered by the following code:
(if (listp marker)
(and (projectile-verify-files marker) project-type)
(and (funcall marker) project-type))
marker
could be both a function or a list and this if
covers both cases.
It works fine if marker
is something defined with defun
, but blows up for lambdas,
as listp
returns t
for them. The solution to the bug was pretty simple:
(if (functionp marker)
(and (funcall marker) project-type)
(and (projectile-verify-files marker) project-type))
I guess that’s the lesson from today’s post - if something can be both a lambda and list, you definitely
want to have the functionp
check first.
That’s all I have for you today. Keep hacking!
P.S. Feel free to share your favourite weird things about Emacs Lisp in the comments!