I am excited to announce the first release of Llama, a package that
implements anonymous function literals for Emacs-Lisp compact
syntax for short lambda
s, without relying on a C patch to Emacs or
adding an additional pair of parentheses.
Instead of:
(lambda (a _ c &rest d) (foo a (bar c) d))
you can use the ##
lisp macro and write:
(##foo % (bar %3) %*)
which expands to:
(lambda (% _%2 %3 &rest %*) (foo % (bar %3) %*))
Note that there really does not have to be any whitespace between ##
and foo
, and did I mention that the C parts of Emacs remain untouched?!
Update: I have come up with a second syntax, which does not put
anything before the opening parenthesis and looks like (l'foo %)
.
Unlike with my original llama
idea I am no longer suggesting making
it look like some character(s) appear before the paren using font-lock
or similar trickery (see below). If you so desire, then you could
however use prettify-symbols-mode
to display it as e.g. (ƒ'foo
%)
. This approach is implemented in l
.
Unfortunately compact syntax for short lambda
s won’t be added to
Emacs anytime soon. IMO the arguments as to why we would like to have
that has been layed out convincingly but the proposal has been
rejected anyway.
Several packages exist that implement anonymous function literals, but until now they all either are waiting for a patch to the C part be merged into Emacs, or they depart too far from the ideal syntax.
In a stroke of luck I discovered a loophole that allows us to have almost the syntax that we want without having to convince anyone.
$(foo %) is what I would have used if it were up to me. #(foo %) works just as well for me. ##(foo %) is similar enough to that. (##foo %) is the loophole that I discovered.
Even though there is no space between the second #
and foo
, this
last form is read as a list with three arguments (## foo %)
and it
is also indented the way we want!
(##foo % bar)
This is good enough for me, but with a bit of font-lock trickery, we can even get it to be display like this:
##(foo % bar)
This is completely optional and you have to opt-in by enabling
llama-mode
(or the global variant global-llama-mode
).
An unfortunate edge-case exists that you have to be aware off; if no argument is placed on the same line as the function, then Emacs does not indent as we would want it too:
(##foo ##(foo bar) which llama-mode displays as bar)
I recommend that in this case you simply write this instead:
(## foo ##( foo bar) which llama-mode displays as bar)
It is my hope that this package helps to eventually get similar syntax into Emacs itself, by demonstrating that this is useful and that people want to use it.
#(foo %)
https://github.com/abo-abo/short-lambda
with a patch to the C part of Emacs($ (foo %))
https://github.com/cadadr/elisp/blob/devel/dollar.el(fn (foo <>))
https://github.com/troyp/fn.elIn 2015 Oleh Krehel (@abo-abo) proposed his Clojure-like syntactic
sugar for an anonymous function literal on emacs-devel
. In
2020 his implementation and a few others were discussed on
the mailing list again, as part of a (much) bigger discussion about
dash.el
and s.el
. The topic also occasionally comes up on
r/emacs.
I think Oleh and others made a good case arguing for the introduction of this new syntax but it wasn’t enough to overcome the resistance and I am not sure I can add much, except for an implementation that does not require upfront approval.
Admittedly I have a hard time even just explaining why we want this new syntax; I find it so obviously desirable. I can also understand that from a certain stylistic point of view the new syntax is undesirable; I just couldn’t accept that this should keep me from writing pulp fiction and so I successfully went looking for a workaround.
For extended context you might also want to read the original discussion mentioned above.
Many people seem to dislike having to use the traditional lambda
syntax in certain cases, as is brought to light by the popularity
of dash
’s anaphoric variants of most of its functions that take a
function as argument.
Oleh disliked the anaphoric variants and that is a major reason why he implemented the new syntax; he wanted to give authors a better, universal alternative. (I want that too, but also I really like the new syntax.)
Authors cannot be forced to use the lambda
syntax, many authors do
whatever is necessary to get the short-hand syntax, regardless of
whether it has the blessing of the Emacs maintainers.
One argument that was presented against the new syntax was “think of the children”, the idea being that new non-programmer users will get very confused by the new syntax. While this is likely to happen, we also have backquote syntax and locating the documentation about that is equally challenging.
The success of dash
made it possible to have things like if-let*
and thread-first
in Emacs, but it failed to bring about anonymous
function literals.
As mentioned before, it is my hope that llama
helps to eventually
get similar syntax into Emacs itself, by demonstrating that this is
useful and that people want to use it.