Emacs Lisp Lambda Expressions Are Not Self-Evaluating
nullprogram.com
nullprogram.com
a list (lambda () (print :foo)) is not code:
CL-USER 10 > (let ((l '(lambda () (print :foo))))
(funcall l))
Error: Argument to apply/funcall is not a function: (LAMBDA NIL (PRINT :FOO)).
But the unquoted lambda form is code, since Common Lisp has a LAMBDA macro CL-USER 13 > (let ((l (lambda () (print :foo))))
(funcall l))
:FOO
:FOO
The LAMBDA macro transforms it into a FUNCTION special form with an embedded lambda expression: CL-USER 14 > (macroexpand-1 '(lambda () (print :foo)))
(FUNCTION (LAMBDA NIL (PRINT :FOO)))
Thus in Common Lisp we can evaluate:a) the special form FUNCTION:
(FUNCTION (LAMBDA () (PRINT :FOO)))
b) the same, but using #' as a short version: #'(LAMBDA () (PRINT :FOO))
c) or the macro LAMBDA, which expands into a) (LAMBDA () (PRINT :FOO)) ;; Call a function object held in a variable
(let ((add (lambda (a b) (+ a b))))
(funcall add 1 2))
vs ;; Direct execution of a lambda expression
((lambda (a b) (+ a b)) 1 2)
Macro expansion can place a literal or generated lambda expression there instead of using FUNCALL at all.I know exactly the spot in the code where they could do what you suggest, because I've often wondered why they don't.
elisp gets a bad rap. But it's mostly self-inflicted.
Also http://www.patrickkphillips.com/grammar/is-it-a-bad-rap-or-b...
A “rap sheet” is a criminal record, and a “bum rap” meant a false accusation (or even a false conviction). Even when the charge was valid, it should come as no surprise, a guilty party might claim it was a “bum rap” just to save face.
Had no idea what a bad rap actually meant.
Not quite. This, for example, does not work:
(defmacro foo () '(lambda (x) x))
((foo) 1)
A macro can expand into a form whose CAR is a literal lambda expression, but because there is always an equivalent LET form I can't think of a circumstance where this can do anything but obfuscate the code.
Personally, I think this is a flaw in the design of CL. Long ago I proposed an extension that would allow the CAR of a form to be a macro:
http://www.flownet.com/ron/lisp/combination-hook.lisp
I think it's cool for pedagogy because it lets you do things like directly define the Y combinator in CL without a ton of FUNCALLs. But it never caught on.
(let ((l '(lambda () (print :foo))))
(funcall (coerce l 'function)))
not to mention passed to eval or compile.So then comes the perennial reminder of Guile/Emacs. There'd be no unexec (in theory) and while this appears to be design-intent from a Common Lisp, maybe it could be cleaned up in bytecode. The last Guile/Emacs push was, I think, a Google SoC project with some community followup from someone who knows far more about Emacs and Lisp than I. Guile 2.2 is out and is really sweet (fast, feels modern, kind of exciting). I wonder if it's time for another push to completion? Has anyone gave the experimental branch a spin lately?
Guile/Emacs offers a way to clear a staggering amount of baggage, offering some great features, while mostly keeping add-on packages compatible. You'd think it would get more love. I use Emacs (having switch from Vim because of elisp) but I'm definitely not well positioned to do anything here :/. As it is, I'm a very strange Emacs user: no emacs-server and always '-nw' inside tmux.
Not to say we shouldn't shake off some baggage. Just at some point having things "tidy" is purely an indulgence.
The whole lisp implementation is emacs is a bit crummy, but I don't get the excessive criticism against unexec. I consider lexical binding a much a much bigger oversight.