emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Use the new let-opt macro in place of pcase-let in lisp-mode.el


From: Oleh Krehel
Subject: Use the new let-opt macro in place of pcase-let in lisp-mode.el
Date: Mon, 18 May 2015 17:16:44 +0200

Hi all,

As I was trying to figure out how `indent-sexp' works, I got the warning
about an unused lexical var `el-kws-re'.  This type of bug isn't easy to
fix without knowing how `pcase-let' works, and even though it's obvious
what it does in this case, it still very inconvenient:

Instead of a single `kill-sexp' or a comment char, as would be the case
with a plain `let', I would have to remove the fifth symbol in a list of
length 10, and make sure that in the list one page down the fifth sexp
in a list of length 10 is removed.

As I understood, all this hassle is for not having to call `regexp-opt'
at run-time, but instead at compile-time.  For your consideration, I add
a new macro named `let-opt' that is more efficient (I assume,
`macroexpand' doesn't work properly for `pcase-let') than `pcase-let' in
this case, and also much more simple and straightforward.

Here's a small example based on the patch. Using `pcase-let':

(pcase-let
    ((`(,var1 ,var2)
      (eval-when-compile
        (let ((lisp-fdefs '("defmacro" "defsubst" "defun"))
              (el-fdefs '("define-advice" "defadvice" "defalias")))
          (list (regexp-opt lisp-fdefs)
                (regexp-opt (append lisp-fdefs el-fdefs)))))))
  (defconst temp-el-keywords var1)
  (defconst temp-cl-keywords var2))

Here's the equivalent with `let-opt':

(let-opt ((lisp-fdefs '("defmacro" "defsubst" "defun"))
          (el-fdefs '("define-advice" "defadvice" "defalias")))
  (let ((var1 (opt (regexp-opt lisp-fdefs)))
        (var2 (opt (regexp-opt (append lisp-fdefs el-fdefs)))))
    (defconst temp-el-keywords var1)
    (defconst temp-cl-keywords var2)))

And here's the definition of `let-opt':

(defmacro let-opt (bindings &rest body)
  "Like `let', but allows for compile time optimization.
Expressions wrapped with `opt' will be subsituted for their values.
\n(fn BINDINGS BODY)"
  (declare (indent 1) (debug let))
  (let ((bnd (mapcar (lambda (x) (cons (car x) (eval (cadr x))))
                     bindings)))
    `(cl-macrolet ((opt (&rest body)
                        (list 'quote (eval (cons 'progn body) ',bnd))))
       ,@body)))

In my own config, I've also set (defalias 'opt 'identity), so that I can
just incrementally eval stuff when debugging.

Please let me know if you have any comments on this, whether the new
code is basically correct (maybe there are some corner cases that need
to be checked, or there already exists a similar macro), and if it's
appropriate to merge this patch. The disadvantage of the new macro is
that several `let-opt' can't be nested currently, but maybe it's not
needed anyway.

Oleh

Attachment: 0001-Add-let-opt-macro-instead-of-using-pcase-let.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]