How to avoid use of `lexical-let`












3















I have a macro that intends to creates a closure:



; -*- lexical-binding: t -*-
(defmacro repro ()
(let ((kmap-sym (gensym "kmap-")))
`(let ((,kmap-sym (make-sparse-keymap)))
(define-key ,kmap-sym "a"
(lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
,kmap-sym)))

;; only works when lexical-binding: t in the current file
(funcall (lookup-key (repro) "a"))


Although lexical-binding is t in the file where the macro is defined, (funcall (lookup-key (repro) "a")) fails with the error (void-variable kmap-30252) whenever it is evaluated in a different file where lexical-binding is nil.



Since I can't control where the macro will be used, I considered going back to using lexical-let for the inner let in the example, which does work regardless of where the macro is invoked.



(defmacro repro ()
(let ((kmap-sym (gensym "kmap-")))
`(lexical-let ((,kmap-sym (make-sparse-keymap)))
(define-key ,kmap-sym "a"
(lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
,kmap-sym)))

;; this works in any file
(funcall (lookup-key (repro) "a"))


But lexical-let requires cl, which I would like to avoid, and unfortunately lexical-let is not defined in cl-lib.



What options do I have for creating a closure?



Should the macroexpansion of repro always expand into lexical bindings given that lexical-binding is t where the macro is defined?










share|improve this question





























    3















    I have a macro that intends to creates a closure:



    ; -*- lexical-binding: t -*-
    (defmacro repro ()
    (let ((kmap-sym (gensym "kmap-")))
    `(let ((,kmap-sym (make-sparse-keymap)))
    (define-key ,kmap-sym "a"
    (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
    ,kmap-sym)))

    ;; only works when lexical-binding: t in the current file
    (funcall (lookup-key (repro) "a"))


    Although lexical-binding is t in the file where the macro is defined, (funcall (lookup-key (repro) "a")) fails with the error (void-variable kmap-30252) whenever it is evaluated in a different file where lexical-binding is nil.



    Since I can't control where the macro will be used, I considered going back to using lexical-let for the inner let in the example, which does work regardless of where the macro is invoked.



    (defmacro repro ()
    (let ((kmap-sym (gensym "kmap-")))
    `(lexical-let ((,kmap-sym (make-sparse-keymap)))
    (define-key ,kmap-sym "a"
    (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
    ,kmap-sym)))

    ;; this works in any file
    (funcall (lookup-key (repro) "a"))


    But lexical-let requires cl, which I would like to avoid, and unfortunately lexical-let is not defined in cl-lib.



    What options do I have for creating a closure?



    Should the macroexpansion of repro always expand into lexical bindings given that lexical-binding is t where the macro is defined?










    share|improve this question



























      3












      3








      3








      I have a macro that intends to creates a closure:



      ; -*- lexical-binding: t -*-
      (defmacro repro ()
      (let ((kmap-sym (gensym "kmap-")))
      `(let ((,kmap-sym (make-sparse-keymap)))
      (define-key ,kmap-sym "a"
      (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
      ,kmap-sym)))

      ;; only works when lexical-binding: t in the current file
      (funcall (lookup-key (repro) "a"))


      Although lexical-binding is t in the file where the macro is defined, (funcall (lookup-key (repro) "a")) fails with the error (void-variable kmap-30252) whenever it is evaluated in a different file where lexical-binding is nil.



      Since I can't control where the macro will be used, I considered going back to using lexical-let for the inner let in the example, which does work regardless of where the macro is invoked.



      (defmacro repro ()
      (let ((kmap-sym (gensym "kmap-")))
      `(lexical-let ((,kmap-sym (make-sparse-keymap)))
      (define-key ,kmap-sym "a"
      (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
      ,kmap-sym)))

      ;; this works in any file
      (funcall (lookup-key (repro) "a"))


      But lexical-let requires cl, which I would like to avoid, and unfortunately lexical-let is not defined in cl-lib.



      What options do I have for creating a closure?



      Should the macroexpansion of repro always expand into lexical bindings given that lexical-binding is t where the macro is defined?










      share|improve this question
















      I have a macro that intends to creates a closure:



      ; -*- lexical-binding: t -*-
      (defmacro repro ()
      (let ((kmap-sym (gensym "kmap-")))
      `(let ((,kmap-sym (make-sparse-keymap)))
      (define-key ,kmap-sym "a"
      (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
      ,kmap-sym)))

      ;; only works when lexical-binding: t in the current file
      (funcall (lookup-key (repro) "a"))


      Although lexical-binding is t in the file where the macro is defined, (funcall (lookup-key (repro) "a")) fails with the error (void-variable kmap-30252) whenever it is evaluated in a different file where lexical-binding is nil.



      Since I can't control where the macro will be used, I considered going back to using lexical-let for the inner let in the example, which does work regardless of where the macro is invoked.



      (defmacro repro ()
      (let ((kmap-sym (gensym "kmap-")))
      `(lexical-let ((,kmap-sym (make-sparse-keymap)))
      (define-key ,kmap-sym "a"
      (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
      ,kmap-sym)))

      ;; this works in any file
      (funcall (lookup-key (repro) "a"))


      But lexical-let requires cl, which I would like to avoid, and unfortunately lexical-let is not defined in cl-lib.



      What options do I have for creating a closure?



      Should the macroexpansion of repro always expand into lexical bindings given that lexical-binding is t where the macro is defined?







      elisp-macros lexical-scoping let-binding lexical-binding






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 12 '18 at 21:24







      erjoalgo

















      asked Nov 12 '18 at 20:18









      erjoalgoerjoalgo

      4411314




      4411314






















          3 Answers
          3






          active

          oldest

          votes


















          1














          Not very sure if the result meets your expectation.



          (defun foo (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))

          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (foo ,kmap-sym))
          ,kmap-sym)))

          (setq lexical-binding nil)
          ;; => nil

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"

          (setq lexical-binding t)
          ;; => t

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"


          The following does the same without using a top-level defun.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-"))
          (fun (lambda (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (,fun ,kmap-sym))
          ,kmap-sym)))





          share|improve this answer


























          • I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

            – erjoalgo
            Nov 12 '18 at 22:35













          • @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

            – xuchunyang
            Nov 12 '18 at 22:51





















          2














          There is an ugly workaround using eval with the optional argument LEXICAL set to t.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(eval
          '(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
          ,kmap-sym)
          t)))


          It is ugly since the associated quoting prevents byte-compilation.






          share|improve this answer
























          • it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

            – erjoalgo
            Nov 12 '18 at 21:32



















          2














          Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding:



          (defmacro repro ()
          (let* ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          ',(lambda () (interactive) (message "kmap is %S" (symbol-value kmap-sym))))
          ,kmap-sym)))


          The other option I use nowadays is to do something like



          (defmacro ...
          (if (not lexical-binding)
          (error "Macro `foo` can't be used with dynamic binding"))
          ...))


          the variable lexical-binding can be relied upon (while expanding the macro) to indicate whether the returned code will be run with lexical or dynamic binding.






          share|improve this answer
























          • I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

            – erjoalgo
            Nov 27 '18 at 9:51













          • @erjoalgo: Was this code placed in a file that uses lexical-binding?

            – Stefan
            Nov 27 '18 at 16:31











          • yes (insert filler chars)

            – erjoalgo
            Dec 2 '18 at 9:15











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "583"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f45949%2fhow-to-avoid-use-of-lexical-let%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Not very sure if the result meets your expectation.



          (defun foo (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))

          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (foo ,kmap-sym))
          ,kmap-sym)))

          (setq lexical-binding nil)
          ;; => nil

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"

          (setq lexical-binding t)
          ;; => t

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"


          The following does the same without using a top-level defun.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-"))
          (fun (lambda (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (,fun ,kmap-sym))
          ,kmap-sym)))





          share|improve this answer


























          • I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

            – erjoalgo
            Nov 12 '18 at 22:35













          • @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

            – xuchunyang
            Nov 12 '18 at 22:51


















          1














          Not very sure if the result meets your expectation.



          (defun foo (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))

          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (foo ,kmap-sym))
          ,kmap-sym)))

          (setq lexical-binding nil)
          ;; => nil

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"

          (setq lexical-binding t)
          ;; => t

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"


          The following does the same without using a top-level defun.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-"))
          (fun (lambda (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (,fun ,kmap-sym))
          ,kmap-sym)))





          share|improve this answer


























          • I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

            – erjoalgo
            Nov 12 '18 at 22:35













          • @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

            – xuchunyang
            Nov 12 '18 at 22:51
















          1












          1








          1







          Not very sure if the result meets your expectation.



          (defun foo (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))

          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (foo ,kmap-sym))
          ,kmap-sym)))

          (setq lexical-binding nil)
          ;; => nil

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"

          (setq lexical-binding t)
          ;; => t

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"


          The following does the same without using a top-level defun.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-"))
          (fun (lambda (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (,fun ,kmap-sym))
          ,kmap-sym)))





          share|improve this answer















          Not very sure if the result meets your expectation.



          (defun foo (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))

          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (foo ,kmap-sym))
          ,kmap-sym)))

          (setq lexical-binding nil)
          ;; => nil

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"

          (setq lexical-binding t)
          ;; => t

          (funcall (lookup-key (repro) "a"))
          ;; => "kmap is (keymap (97 lambda nil (interactive) (message kmap is %s (quote #0))))"


          The following does the same without using a top-level defun.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-"))
          (fun (lambda (keymap)
          `(lambda () (interactive) (message "kmap is %s" ',keymap)))))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (,fun ,kmap-sym))
          ,kmap-sym)))






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 12 '18 at 22:56

























          answered Nov 12 '18 at 21:43









          xuchunyangxuchunyang

          8,5941925




          8,5941925













          • I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

            – erjoalgo
            Nov 12 '18 at 22:35













          • @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

            – xuchunyang
            Nov 12 '18 at 22:51





















          • I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

            – erjoalgo
            Nov 12 '18 at 22:35













          • @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

            – xuchunyang
            Nov 12 '18 at 22:51



















          I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

          – erjoalgo
          Nov 12 '18 at 22:35







          I was considering something like this based on the way one can create a javascript closure. But I wasn't sure if there was another alternative. I was also hoping to provide this closure anonymously instead of relying on a top-level function.

          – erjoalgo
          Nov 12 '18 at 22:35















          @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

          – xuchunyang
          Nov 12 '18 at 22:51







          @erjoalgo You can put the top-level function into the macro, (let ((f (lambda (keymap) `(lambda () ...))))), it does the same.

          – xuchunyang
          Nov 12 '18 at 22:51













          2














          There is an ugly workaround using eval with the optional argument LEXICAL set to t.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(eval
          '(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
          ,kmap-sym)
          t)))


          It is ugly since the associated quoting prevents byte-compilation.






          share|improve this answer
























          • it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

            – erjoalgo
            Nov 12 '18 at 21:32
















          2














          There is an ugly workaround using eval with the optional argument LEXICAL set to t.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(eval
          '(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
          ,kmap-sym)
          t)))


          It is ugly since the associated quoting prevents byte-compilation.






          share|improve this answer
























          • it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

            – erjoalgo
            Nov 12 '18 at 21:32














          2












          2








          2







          There is an ugly workaround using eval with the optional argument LEXICAL set to t.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(eval
          '(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
          ,kmap-sym)
          t)))


          It is ugly since the associated quoting prevents byte-compilation.






          share|improve this answer













          There is an ugly workaround using eval with the optional argument LEXICAL set to t.



          (defmacro repro ()
          (let ((kmap-sym (gensym "kmap-")))
          `(eval
          '(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          (lambda () (interactive) (message "kmap is %s" ,kmap-sym)))
          ,kmap-sym)
          t)))


          It is ugly since the associated quoting prevents byte-compilation.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 12 '18 at 21:22









          TobiasTobias

          12.8k1833




          12.8k1833













          • it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

            – erjoalgo
            Nov 12 '18 at 21:32



















          • it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

            – erjoalgo
            Nov 12 '18 at 21:32

















          it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

          – erjoalgo
          Nov 12 '18 at 21:32





          it's nice to know this exists, although I'd prefer (eval-when-compile (require 'cl-lib)) over this.

          – erjoalgo
          Nov 12 '18 at 21:32











          2














          Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding:



          (defmacro repro ()
          (let* ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          ',(lambda () (interactive) (message "kmap is %S" (symbol-value kmap-sym))))
          ,kmap-sym)))


          The other option I use nowadays is to do something like



          (defmacro ...
          (if (not lexical-binding)
          (error "Macro `foo` can't be used with dynamic binding"))
          ...))


          the variable lexical-binding can be relied upon (while expanding the macro) to indicate whether the returned code will be run with lexical or dynamic binding.






          share|improve this answer
























          • I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

            – erjoalgo
            Nov 27 '18 at 9:51













          • @erjoalgo: Was this code placed in a file that uses lexical-binding?

            – Stefan
            Nov 27 '18 at 16:31











          • yes (insert filler chars)

            – erjoalgo
            Dec 2 '18 at 9:15
















          2














          Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding:



          (defmacro repro ()
          (let* ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          ',(lambda () (interactive) (message "kmap is %S" (symbol-value kmap-sym))))
          ,kmap-sym)))


          The other option I use nowadays is to do something like



          (defmacro ...
          (if (not lexical-binding)
          (error "Macro `foo` can't be used with dynamic binding"))
          ...))


          the variable lexical-binding can be relied upon (while expanding the macro) to indicate whether the returned code will be run with lexical or dynamic binding.






          share|improve this answer
























          • I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

            – erjoalgo
            Nov 27 '18 at 9:51













          • @erjoalgo: Was this code placed in a file that uses lexical-binding?

            – Stefan
            Nov 27 '18 at 16:31











          • yes (insert filler chars)

            – erjoalgo
            Dec 2 '18 at 9:15














          2












          2








          2







          Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding:



          (defmacro repro ()
          (let* ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          ',(lambda () (interactive) (message "kmap is %S" (symbol-value kmap-sym))))
          ,kmap-sym)))


          The other option I use nowadays is to do something like



          (defmacro ...
          (if (not lexical-binding)
          (error "Macro `foo` can't be used with dynamic binding"))
          ...))


          the variable lexical-binding can be relied upon (while expanding the macro) to indicate whether the returned code will be run with lexical or dynamic binding.






          share|improve this answer













          Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding:



          (defmacro repro ()
          (let* ((kmap-sym (gensym "kmap-")))
          `(let ((,kmap-sym (make-sparse-keymap)))
          (define-key ,kmap-sym "a"
          ',(lambda () (interactive) (message "kmap is %S" (symbol-value kmap-sym))))
          ,kmap-sym)))


          The other option I use nowadays is to do something like



          (defmacro ...
          (if (not lexical-binding)
          (error "Macro `foo` can't be used with dynamic binding"))
          ...))


          the variable lexical-binding can be relied upon (while expanding the macro) to indicate whether the returned code will be run with lexical or dynamic binding.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 13 '18 at 13:48









          StefanStefan

          18.9k2461




          18.9k2461













          • I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

            – erjoalgo
            Nov 27 '18 at 9:51













          • @erjoalgo: Was this code placed in a file that uses lexical-binding?

            – Stefan
            Nov 27 '18 at 16:31











          • yes (insert filler chars)

            – erjoalgo
            Dec 2 '18 at 9:15



















          • I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

            – erjoalgo
            Nov 27 '18 at 9:51













          • @erjoalgo: Was this code placed in a file that uses lexical-binding?

            – Stefan
            Nov 27 '18 at 16:31











          • yes (insert filler chars)

            – erjoalgo
            Dec 2 '18 at 9:15

















          I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

          – erjoalgo
          Nov 27 '18 at 9:51







          I tried this solution pastebin.com/8ntq4fTJ but it still failed for me with "Symbol’s value as variable is void: kmap-sym"

          – erjoalgo
          Nov 27 '18 at 9:51















          @erjoalgo: Was this code placed in a file that uses lexical-binding?

          – Stefan
          Nov 27 '18 at 16:31





          @erjoalgo: Was this code placed in a file that uses lexical-binding?

          – Stefan
          Nov 27 '18 at 16:31













          yes (insert filler chars)

          – erjoalgo
          Dec 2 '18 at 9:15





          yes (insert filler chars)

          – erjoalgo
          Dec 2 '18 at 9:15


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Emacs Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f45949%2fhow-to-avoid-use-of-lexical-let%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Full-time equivalent

          さくらももこ

          13 indicted, 8 arrested in Calif. drug cartel investigation