I want to improve my Elisp, but despite reading about the differences between functions and macros (including discussions here in Emacs SE and on Reddit), I still find examples where the distinction confuses me.

For example, in the "starter-pack" Radian, a macro can be found which wraps use-package ensuring some sort of partial application:

(defmacro use-feature (name &rest args)
  "Like `use-package', but with `straight-use-package-by-default' disabled."
  (declare (indent defun))
  `(use-package ,name
     :straight nil

As a case study, would it not be possible to achieve the same with a defun? After all, this seems like a simple case of partial application, or am I missing something? Do we need a macro here just because use-package itself is a macro which we don't want a defun body to evaluate?

And would there be a safe way to improve this macro to take care of a possibly unwanted case (use-feature foo :straight t)?

  • 1
    Macros can manage their raw arguments, while functions can't. If use-package is a functions, user will have to quote the arguments which is inconvenient and ugly, e.g., (use-package 'foo :if '(<= 1 2) :commands #'foo-bar :bind '("C-c C-c" . foo)), the same applies to use-feature, and if use-feature is not a macro, the use of it won't be like use-package.
    – xuchunyang
    Commented Mar 25, 2019 at 13:54
  • 4
    What @xuchunyang said, where "raw" args means they are not evaluated when passed to the macro code. A macro can do anything it likes with/to any arg it is passed, including ignore it or evaluate it. A macro produces code, which is then evaluated. A macro can do anything with its args, but it is not about partial application per se. Partial application is about function application to fewer than all of the function's args. If an arg to a macro is a function then it can apply it partially to some args. Otherwise, there is no connection between partial eval and macros.
    – Drew
    Commented Mar 25, 2019 at 14:05
  • 5
    As usual, a good way to learn about Elisp macros is to ask Emacs. C-h i, then choose Emacs Lisp Intro. In that intro-to-Elisp manual you'll find node Lisp macro, which will help. Or choose Elisp, the Emacs-Lisp reference and guide. There you'll find node Macros, which fills you in about Elisp macros. Much better than getting ad hoc answers here or on Reddit (IMHO). You're not the first person to learn Lisp macros - trust Emacs to help.
    – Drew
    Commented Mar 25, 2019 at 14:45
  • At least one of these comments deserves to be promoted to an actual answer. Commented Aug 24, 2020 at 16:56

1 Answer 1


This is an old question, but every question deserves an answer. You basically had it with "because use-package itself is a macro which we don't want a defun body to evaluate". More specifically, it couldn't be a defun, because:

  1. Order Of Evaluation: use-package defines the order of evaluation (before and after loading its package) with, for example, the :init, :config and :after keywords. If use-feature were a defun, all arguments would be evaluated in order.

  2. Quoting: Some use-package sections, such as :bind take unquoted data as arguments (which would throw an error for not being a function), and many take an unquoted symbols (which emacs would try to evaluate as variables). You could require the user to manually quote everything, but that would make the use-feature API very different from use-package.

To answer the finall question at the end of the post - if there are 2 :straight keywords, the order of evaluation depends on the internals of use-package. If this version of the macro lets the user override it, swapping the lines ,@args and :straight t would probably change that behaviour. But might not, and you probably can't know without reading the code of use-package.

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.