Many have suggested adding a lambda reader construct to Emacs Lisp: something like #(princ $1), which would be translated to (lambda (x) (princ x)).

Well, it turns out that you can (ab)use the existing reader constructs for this purpose. Specifically, ,x and ,@x are translated to (\, x) and (\,@ x), which are without meaning outside of a backquoted list.

That means that it is legal to define and use \, as a function or macro:

(defmacro \, (body) "Return an anonymous function. In BODY, symbols of the type $N, where N is a non-zero, positive number, represent positional arguments. $* represents a list of optional remaining arguments. ,(+ $1 $2) expands to (lambda ($1 $2) (+ $1 $2)). See `lambda'." (let ((total 0) rest) (cl-labels ((search (form) (if (consp form) (progn (search (car form)) (search (cdr form))) (if (eq form '$*) (setq rest t) (let ((s (prin1-to-string form))) (if (string-match "^\\$\\([1-9][0-9]*\\)$" s) (let ((n (string-to-number (match-string 1 s)))) (setq total (max total n))))))))) (search body)) `(lambda ,(append (cl-loop for n from 1 upto total collect (intern (format "$%d" n))) (and rest '(&rest $*))) ,body))) 

With this macro, you can replace

(mapcar (lambda (x) (with-output-to-string (princ x))) objects) 

with

(mapcar ,(with-output-to-string (princ $1)) objects) 

If you want your lambda to accept an unlimited number of arguments, use `$*':

(advice-add 'some-function :before ,(dolist (x $*) (message "%s" x))) 

What are the downsides? Strictly, there is only one. The docstring for the macro above will not be displayed in Emacs' help system, which will always display the built-in information about ,.

submitted by /u/quote-only-eeee
[link] [comments]