[comp.emacs] Problem with macros

beck@qtp.ufl.edu (Sullivan Beck) (11/14/90)

I am trying to learn how to use macros but am having some problems
with the 'quote' command, mainly with trying to pass arguments to
the macro.  For example, here's a simple function which will insert
a character in a buffer:

(defun test (char)
  (save-excursion
    (set-buffer (get-buffer tmp-buffer))
    (save-excursion
      (goto-char 1)
      (forward-line 2)
      (forward-char 3)
      (delete-char 1)
      (insert char))))

which works as expected.  I can switch it to a macro using the list
command repeatedly:

(defmacro test (char)
  (list 'save-excursion
        (list 'set-buffer (list 'get-buffer 'tmp-buffer))
        (list 'save-excursion
              (list 'goto-char 1)
              (list 'forward-line 2)
              (list 'forward-char 3)
              (list 'delete-char 1)
              (list 'insert char))))

but I cannot get the quote (which I'd greatly prefer of course) to work.
Here's what I've got:

(defmacro test (char)
  (` (save-excursion
       (set-buffer (get-buffer tmp-buffer))
       (save-excursion
         (goto-char 1)
         (forward-line 2)
         (forward-char 3)
         (delete-char 1)
         (insert char)))))

But this doesn't work.  If I have the following lines in a program:

  (setq char "*")
  (test "!")

the first two will insert the "!" but the third will insert a "*".  Could
someone explain what I am doing wrong (other than I don't really understand
how to use the quote).  Thanks in advance.

S. Beck
beck@qtp.ufl.edu

piet@cs.ruu.nl (Piet van Oostrum) (11/14/90)

>>>>> In message <1183@red15.qtp.ufl.edu>, beck@qtp.ufl.edu (Sullivan Beck)
>>>>> (SB) writes:

SB> (defmacro test (char)
SB>   (` (save-excursion
SB>        (set-buffer (get-buffer tmp-buffer))
SB>        (save-excursion
SB>          (goto-char 1)
SB>          (forward-line 2)
SB>          (forward-char 3)
SB>          (delete-char 1)
SB>          (insert char)))))

SB> But this doesn't work.  If I have the following lines in a program:

SB>   (setq char "*")
SB>   (test "!")

SB> the first two will insert the "!" but the third will insert a "*".  Could
SB> someone explain what I am doing wrong (other than I don't really understand
SB> how to use the quote).  Thanks in advance.

The problem is that you want the "char" in your macro body to be replaced
by the parameter, and not to mean the variable with the name "char". So you
must UNQUOTE char in your macro body as follows:

          (insert ,char)))))

Well, I haven't run the code, but this should work.
-- 
Piet* van Oostrum, Dept of Computer Science, Utrecht University,
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands.
Telephone: +31 30 531806   Uucp:   uunet!mcsun!ruuinf!piet
Telefax:   +31 30 513791   Internet:  piet@cs.ruu.nl   (*`Pete')

worley@compass.com (Dale Worley) (11/15/90)

In article <1183@red15.qtp.ufl.edu> beck@qtp.ufl.edu (Sullivan Beck) writes:
   (defmacro test (char)
     (` (save-excursion
	  (set-buffer (get-buffer tmp-buffer))
	  (save-excursion
	    (goto-char 1)
	    (forward-line 2)
	    (forward-char 3)
	    (delete-char 1)
	    (insert char)))))

     (setq char "*")
     (test "!")

First, remember what a macro does:  The code

	(test "!")

is effectively replaced by
     (save-excursion
	  (set-buffer (get-buffer tmp-buffer))
	  (save-excursion
	    (goto-char 1)
	    (forward-line 2)
	    (forward-char 3)
	    (delete-char 1)
	    (insert char)))

Note that this code is *not* inside the scope of the defmacro, so char is
not bound to "!" when it is executed.  What you want to do is replace
the "char" in the expansion by the value of the argument "char" to the
invocation of the macro.  The way to do this is is to "unquote"
"char".  For example:

	(` (a b (, c)))

If "c" has the value 3, then this evaluates to

	(a b 3)

Therefore, you want the macro body to be

     (` (save-excursion
	  (set-buffer (get-buffer tmp-buffer))
	  (save-excursion
	    (goto-char 1)
	    (forward-line 2)
	    (forward-char 3)
	    (delete-char 1)
	    (insert (, char)))))

When playing around with macros, it can be very useful to use the
macroexpand function to see what particular expressions expand to.
(Set the second (ENVIRONMENT) argument to nil.)

Also, in E-lisp, people use the word "quote" for the form (quote ...)
or '... .  When you are using "`", it is called "backquote".

Dale Worley		Compass, Inc.			worley@compass.com
--
In 1976, Seymour Cray was asked "In twenty years, what language will
supercomputers be programmed in?"  His answer was, "I don't know what
it will *be*, but it will be *called* Fortran."  And now we have
Fortran 8x (now Fortran 90)...