[comp.emacs] save-match-data

quiroz@cs.rochester.edu (Cesar Quiroz) (05/16/89)

In <TALE.89May15161530@imagine.pawl.rpi.edu>, David Lawrence
proposed encapsulating the protection of global match data by using
a function (defun save-match-data (&rest forms) ...).

As functions evaluate their arguments first, this approach requires
you to quote the FORMS, else they will be evaluated in the wrong
environment, thus nullifying the intended protection.  Not to
mention that the second evaluation may cause errors, try for
instance:

    (string-match "a+" "banana")
    (save-match-data (string-match "b+" "banana"))

which should actually be

    (save-match-data '(string-match "b+" "banana"))

A better way is to define a macro, to go along with the syntax of
the special forms save-{excursion,restriction}.  An example follows:

    (require 'cl)
    (defmacro save-match-data (&rest body)
      "Execute the BODY forms, restoring the global value of the match data."
      (let ((original (gensym)))
        (list
         'let (list (list original '(match-data)))
         (list 'unwind-protect
               (cons 'progn body)
               (list 'store-match-data original)))))
    (put 'save-match-data 'lisp-indent-hook 0)

In whose case we see

    (macroexpand '(save-match-data (string "n+" "banana")))
    (let ((G$$_5 (match-data)))
      (unwind-protect 
          (progn (string "n+" "banana"))
        (store-match-data G$$_5)))

as desired.  A minor optimization would be to generate the 'progn
only if the body has 2 or more forms, but that would be most likely
a waste of time.

Cesar
-- 
                                      Cesar Augusto Quiroz Gonzalez
                                      Department of Computer Science
                                      University of Rochester
                                      Rochester,  NY 14627