Emacs lisp lambda with lexical binding?

2019-07-05 23:48发布

问题:

I set out to write this code snippet for "git add -p":

(add-hook
 'diff-mode-hook
 (lambda()            
   (mapc (lambda(k)
           (lexical-let ((kk k))
             (define-key diff-mode-map k
               (lambda()(interactive)
                 (if (region-active-p)
                     (replace-regexp "^." kk
                                     nil
                                     (region-beginning)
                                     (region-end))
                   (insert kk)))))) (list " " "-" "+"))))

It works as I want, it's just the ugliness of 'lexical-let in the middle that bothers me. I had to add it, since the nested lambda didn't see the variable 'k. Is there a better way to write this code? I would prefer some magic function 'lexic-lambda that would allow me to write:

(add-hook
 'diff-mode-hook
 (lambda()            
   (mapc (lexical-lambda(k)
                   (define-key diff-mode-map k
                     (lexical-lambda()(interactive)
                       (if (region-active-p)
                           (replace-regexp "^." k
                                           nil
                                           (region-beginning)
                                           (region-end))
                         (insert k)))))) (list " " "-" "+")))

回答1:

(mapc (lambda (k)
        (define-key diff-mode-map k
          `(lambda ()
             (interactive)
             (if (region-active-p)
                 (replace-regexp "^." ,k
                                 nil
                                 (region-beginning)
                                 (region-end))
               (insert ,k)))))
      (list " " "-" "+"))

Alternatively, since Emacs 24, you can enable lexical bindings locally. Just add ;; -*- lexical-binding: t -*- at the top of the file, and your code should work without the lexical-let wrapper. (See C-h i g (elisp)Lexical Binding RET and C-h i g (elisp)Using Lexical Binding RET.)



标签: git elisp