7

Is there a way to define a macro in an emacs-lisp file in such a way that the macro would not be visible anywhere else once the file is read and evaluated?

Kind of like a temporary macro that goes out of scope at the end of a file?

3
  • 1
    Besides the general solution of using macrolet, remember that it is often the case that you need a particular macro only at byte-compile time. In that case, byte-compiling a file without the macro definition loaded, or just using that file without compiling it, will mean that the code in that file does not have the macro available at runtime. IOW, it knows nothing about the macro.
    – Drew
    Commented Jan 29, 2015 at 6:08
  • 1
    @Drew Oh, so like (eval-when-compile (defmacro ...))?
    – Kirill
    Commented Jan 29, 2015 at 7:33
  • 2
    More like (eval-when-compile (require 'my-macros)) for the files that you want to see the macro definition.
    – Drew
    Commented Jan 29, 2015 at 14:43

1 Answer 1

11

You can always unbind the macro when the file ends. As far as I know, Emacs Lisp doesn't have to worry about asynchronous complexities; the flow of execution is purely linear. Therefore, you can do this:

(defmacro my-test-macro (secret sauce recipe)
   ;; super secret stuff here
   ;; wouldn't want it to LEAK out
   ;; and get stolen by some other files
   )

;; [...] blabitty blah blah [...]

(fmakunbound 'my-test-macro)

The other solution you should look at (which is less hacky) uses cl-macrolet, which is basically a let for macros.

(eval-when-compile (require 'cl-lib))
(cl-macrolet ((my-test-macro (secret sauce recipie)
                 ;; super secret stuff here
                 ;; wouldn't want it to LEAK out
                 ;; and get stolen by some other files
                 ))

  ;; [...] blabitty blah blah [...]

  )

No doubt, this solution is cleaner, although you pay for it by adding another level of indentation. Also, the macro is dynamically bound and could in theory be run asynchronously (although Emacs is a long way from multi-threading).

4
  • I think the first solution won't work in interpreted code...
    – politza
    Commented Jan 29, 2015 at 21:53
  • 1
    @politza pasting (defmacro abc () (message "abc")) (abc) (fmakunbound 'abc) (abc) into *scratch* and doing M-x eval-buffer works for me. You first get "abc" then a symbol's function definition is void abc
    – PythonNut
    Commented Jan 29, 2015 at 23:34
  • 1
    Yes, since Emacs 24.3 introduced eager macro expansion, which I have just discovered.
    – politza
    Commented Jan 29, 2015 at 23:59
  • ...though I don't know, if this is guaranteed to always happen.
    – politza
    Commented Jan 30, 2015 at 0:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.