For Kenny Tilton: Why do I need macros revisited.

Paul Foley see at below.invalid
Sat Aug 23 06:00:35 EDT 2003


On Fri, 22 Aug 2003 11:10:49 -0400, Terry Reedy wrote:

>> Scheme macros are not the same as Lisp macros.  Scheme macros are a
>> lot more complicated (and less useful; but most Scheme implementations
>> also offer Lisp-style macros...)

> Please excuse my confusing of Scheme with Lisp.  I am pleased to find
> that my difficulty in reading the Scheme macro stuff wasn't just me.
> But note that there have been proposals that if Python were to have a
> macro facility, it should be 'hygenic', which I presume means like
> Scheme macros.

> Until some advocate of a Python macro facility adds more detail to the
> proposal beyound 'Lisp/Scheme-like maco facility', it is really hard
> for someone like me, who has used neither, to have much of any
> concrete idea of what is being proposed.

I don't know what others are proposing.

In Lisp, a macro is really just a function like any other (so people
arguing against macros who are not also against functions are clearly
insane!).  It takes two arguments: a "form" (i.e., some Lisp code) and
an "environment" (a fairly useless opaque object), and returns more
Lisp code.  So (a simplified version of) EVAL in a Lisp without macros
might look something like

  (defun eval (form)
    (typecase form
      (symbol (symbol-value form))
      (atom   form)
      (cons   (apply (first form) (mapcar #'eval (rest form))))))

and to add macros, all that's necessary is

  (defun macroexpand (form)
    (if <form is a macro form>
        (macroexpand (funcall (macro-function (first form)) form <environ>))
        form))

  (defun eval (form)
    (let ((form (macroexpand form)))
      (typecase form
        (symbol (symbol-value form))
        (atom   form)
        (cons   (apply (first form) (mapcar #'eval (rest form)))))))


If you write a macro, LIST2, such that (LIST2 1 2 3 ...) expands into
(LIST (LIST 1) (LIST 2) (LIST 3) ...), and then you use it in a
function like

  (defun foo (list)
    (let ((x (list2 1 2 3)))
      ...))

in a Lisp-2 (i.e., a language with separate namespaces for variables
and functions, so you can have both a variable and a function with the
same name at the same time) there's no problem, but in a Lisp-1
(single shared namespace, like Scheme and Python) you'd have a big
problem: when the list2 macro is expanded, "list" is a variable -- the
argument to "foo" -- not the list-constructing function the
macro-writer expected.

So Scheme introduced the so-called "hygienic" macros [a bad name,
implying that non-hygienic macros are "dirty" and to be avoided;
"hygienic" macros are the ones I want to avoid!], where names used in
the macro expansion are in the scope where the macro was defined,
rather than the scope that's in effect where it's expanded, so that
"list" in the expansion refers to the list function, not the argument
to foo, and bindings made by the macro are not visible to code that
comes in from user code.

But Scheme macros are not just functions like Lisp macros, either.  A
Scheme macro is defined as a set of patterns to be matched against
the code, and an associated rewrite rule which specifies the code to
use instead.  [I don't see any reason why these rules need to be
written in a Lispy syntax...]

-- 
Just because we Lisp programmers are better than everyone else is no
excuse for us to be arrogant.                                -- Erann Gat

(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))




More information about the Python-list mailing list