2

Many emacs macros are prefixed with 'with' keyword in elisp. In an imperative language like python, with statement is used to create a temporary variable like this,

with controlled_execution() as tempVar:
     some code

However, in macros like with-current-buffer, with-temp-buffer, with-temp-message, i see with is not used for similar purpose. Can someone explain, in elisp macro, when to prefix a macro name with prefix 'with'? And because these macros are expected to clear their temp variables, do they have any side effect on the main program?

3 Answers 3

5

To add a bit to what phils wrote. with- is usually an indication of resource management, so your initial guess was close (btw. Emacs Lisp is no less imperative language than Python). So, for example, with-current-buffer will enter and exit the specified buffer, i.e. create at start and clean afterwards. with-output-to-string will allocate a buffer where it will collect all output of the forms inside the macro.

The rationale behind these kinds of macros is that sometimes you don't want the user of your macro to deal with resource allocation and deallocation. So, such macros tend to have two distinct features:

  1. They provide a variable bound during macro execution (the one which designates the resource being worked with).
  2. They release acquired resources after the user code finishes.

A typical implementation would do something like this:

(defmacro with-something (var &body body)
  `(let ((var (allocate-var)))
     (unwind-protect ,@body
       (when var (deallocate-var)))))

Where body forms use var resource very similar to how in your Python code you could use the variable declared in as var part.

with-current-buffer is somewhat different since it doesn't expose the buffer variable, but calling buffer-related functions will be equivalent, so there's no real need.

7

The thing the with- function have in common is that they create a code block where something, temporarily, has been changed. Once you have left the code block, things are back to normal.

By "code block" I mean a group of lisp statement grouped together with something that work like progn.

For example:

;; Do something in a buffer
(with-current-buffer another-buffer
  ;; do something in "another-buffer"
  ...
  ...)
;; Here, we're back to the original buffer

Another example:

(with-output-to-temp-buffer "*MyOutput*"
  ;; A "princ" prints to the newly created temporary buffer.
  (princ "Hello World!\n")
  (display-buffer (current-buffer)))
;; A "princ" here will print to whatever "standard-output" points to,
;; typically the echo-area.
1
  • hit the nail....
    – Saravana
    Commented Feb 25, 2015 at 13:16
6

Well just to be clear, with- as a prefix doesn't do anything. It is just a name, so any function or macro could be given a name starting with with- if you so wished.

The convention is that such a macro accepts a &rest BODY argument (i.e. some arbitrary number of forms), which will be evaluated in whatever context the prior arguments have established.

As there is nothing special about these macros, they may or may not have side-effects. Nothing is enforced. The documentation ought to make it fairly clear what each one does.

The naming scheme is intended to make for intuitive code. e.g. (with-current-buffer BUFFER &rest BODY) evaluates BODY with BUFFER set as the current buffer -- which is probably what you'd expect it to do if you saw the code and didn't already know.

1
  • 1
    And, for what it's worth, the with-something-something-something naming convention is also used in Common Lisp. Both elisp and CL built on top of Maclisp, so I'm guessing the naming convention goes back at least that far.
    – Dan
    Commented Feb 25, 2015 at 13:17

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.