29

I have seen progn being used quite a lot as I browse the configuration files of experienced Emacs users. I found this nice explanation of progn, but what I am really curious about is, what is the benefit of using this function? Take for example this snippet (taken from Sacha Chua's configuration):

(use-package undo-tree
  :defer t
  :ensure t
  :diminish undo-tree-mode
  :config
  (progn
    (global-undo-tree-mode)
    (setq undo-tree-visualizer-timestamps t)
    (setq undo-tree-visualizer-diff t)))

Is there any major difference between the above configuration and this?

(use-package undo-tree
  :defer t
  :ensure t
  :diminish undo-tree-mode
  :config
  (global-undo-tree-mode)
  (setq undo-tree-visualizer-timestamps t)
  (setq undo-tree-visualizer-diff t))

I feel like the first example is somehow cleaner, even though it has more syntax, and my intuition is that there might be some kind of performance boost from using progn, but I am not sure. Thank you for any insights!

mustaqim
  • 47
  • 1
  • 6
elethan
  • 4,825
  • 3
  • 30
  • 56
  • 9
    In this particular case there is no difference: use-package will wrap a progn around your :config forms if it is missing. Try it out: you can put point at the end of a (use-package ...) and call M-x pp-macroexpand-last-sexp to see how the macro is expanded. You'll see that it is identical for these two examples. – glucas Dec 03 '15 at 04:23
  • An example where progn is needed: https://emacs.stackexchange.com/questions/39172/emacs-lisp-let-with-while – npostavs Mar 03 '18 at 23:58

3 Answers3

21

progn is typically used when dealing with macros. Some macros (use-package is a macro, last I checked) accept only 1 form, where others consume all remaining forms.

progn is used in the former case to turn a sequence of forms into a single form.

In your examples, the first one uses progn and thus there is 1 form after :config. In the second, there are 3 forms. If the use-package macro only expects 1 form following :config, then it will cause an error.

It is worth noting that using progn works in both cases, while omitting it only works if the macro accepts multiple forms. As a result of this, some people prefer to simply always use progn, because it will always work.

J David Smith
  • 2,675
  • 1
  • 18
  • 27
  • 21
    It really has nothing to do with macros. Some functions and macros have a so-called "implicit progn", meaning that they accept any number of sexps as separate arguments and evaluate them in sequence. Others don't, and instead expect/allow only a single argument where you might want to evaluate multiple sexps in sequence. That's all progn does: it lets you provide a single sexp that when evaluated evaluates the sexp args to progn in sequence. Compare (if true (progn a b c)) with (when true a b c). In both cases, a, b, and c are evaluated in sequence. – Drew Dec 03 '15 at 05:40
  • 1
    @Drew: which is what I said. "implicit progn" -> "consume all remaining forms". I reached to macros as an example because that covers 99% of use cases and makes for a clear answer. I considered adding a note pointing out that progn isn't just for macros, but I didn't feel it added to the answer. There are other use cases, but they are rather uncommon. – J David Smith Dec 03 '15 at 05:42
  • 2
  • 8
    I disagree that 99% of the use cases are for macros etc. Any function or macro can be passed a progn sexp that contains multiple sexps that are evaluated for their side effects, before returning the result of the last of these. It really has nothing to do with macros. Macros "as an example" is fine. Giving the impression that progn exists for macros, and that 99% of its use is for macros, is misleading, IMO. progn is about shoveling a sequence of evaluations into a single sexp (to fit a given expected argument), and it is therefore about side effects. – Drew Dec 03 '15 at 14:47
  • @Drew glad you made that clarification here; anyone reading the accepted answer should read your comments first. – Emacs User Dec 03 '15 at 15:36
  • @Drew: I can't think of any time I've used progn except for as the input to a macro. Can you give an example of where it'd be used aside from as input to a macro or special form? I don't follow your logic about it being about side effects. – J David Smith Dec 03 '15 at 16:20
  • 5
  • progn was introduced in Lisp 1.5 (see section The Program Feature), in 1962, long before macros were added to Lisp. The purpose is to sequentially evaluate expressions for their side effects. 2. See progn for how Emacs itself introduces progn to Elisp programmers. See the zap-to-char code for a simple use case.
  • – Drew Dec 03 '15 at 17:42
  • 1
    @Drew: while I understand your point now, I don't believe that's the way to answer this question. Even though that was the original intention, in my experience it is very rarely used in that fashion these days. Most of the examples one will encounter when seeing elisp are of progn to pass multiple forms as a single form. The fact that it originally did this to explicitly order forms for their side-effects is not particularly relevent in emacs lisp, even if it is still relevant in other lisps – J David Smith Dec 03 '15 at 22:40
  • 1
    @Drew: as an aside: the ordering of lisp forms is implicit in emacs lisp and the usage for side effects is obvious (by virtue of the fact that otherwise it wouldn't be useful for the main use case in emacs). I don't think that the definition of what progn is accurately depicts what we now use it for – J David Smith Dec 03 '15 at 22:41
  • 3
    We can agree to disagree. My point is that progn has nothing whatsoever to do with macros. Its purpose is of course "to pass multiple forms as a single form" (your words) - whether to a function or a macro or a special form, but also to "Eval BODY forms sequentially and return value of last one" (doc string). Now as ever ("these days", indeed!). An ordered evaluation is important only for side effects, obviously. A given use case (macro or not) might or might not care about the evaluation order, but that is irrelevant. And Emacs Lisp is not exceptional in any way in this regard. – Drew Dec 04 '15 at 02:54
  • Just a note of support forDrew.The macro link is news to me. It's simply to allow multiple forms in just about every use case I have seen. "macros" don't even appear on the radar. – RichieHH Dec 13 '20 at 02:13