No macros in Python

Bruce Hoult bruce at
Wed Jan 1 09:48:58 CET 2003

In article <x78yyqiwle.fsf at>, Mike Meyer <mwm at> 

> Peter Hansen <peter at> writes:
> > Mike Meyer wrote:
> > > 
> > > Python doesn't have macros. On the other hand, looking at the world
> > > through OO glasses rather than S-expression glasses means you don't
> > > need macros as often. But the topic comes up at irregular intervals,
> > > so someone may eventually come up with a way of doing macros in Python
> > > that is right - at which point it'll be added.
> > In what way would macros (as I understand them... from C for example)
> > improve Python, other than possibly a small improvement in performance?
> C macros are a very poor example of the species. I was referring to
> lisp-like macros, where you get the full functionality of the language
> to manipulate the code that the macro is dealing with.

That's pretty cool, and the most flexible it's possibel to get, but I 
think it's overkill for most cases, and not always the easiest to write 
or to understand.

> This works particularly well in lisp, where the code is handed to the
> macro preparsed and stored in one of the fundamental data structures
> of the language. That makes writing macros easier. Since all code is
> written in that data structure, they also fit naturally into the
> language when they are invoked.


> Any macro facility added to python has to deal with both these
> problems. There needs to be some way to avoid the macro author having
> to write a python parser to manipulate the code, and some way for them
> to be invoked that fits well with the language.

You should take a look at macros in Dylan.  You can implement pretty 
much every macro in _On Lisp_, in a language with conventional syntax.  
And you don't have to write a parser!  Dylan macros work by pattern 
matching and replacement on token sequences.

> As for what this lets you do, the answer is "lots of things". Much of
> what is part of the syntax of Python can be implemented as macros in
> lisp - short-circuit boolean operators come readily to mind.

In the Dylan standard library:

define macro \&
    { \& (?left:expression, ?right:expression) }
      => { if (?left) ?right end }

define macro \|
    { \| (?left:expression, ?right:expression) }
      => { let temp = ?left; if (temp) temp else ?right end }

| and & are infix operators in Dylan, so to talk about them as functions 
(or to define them) you need to refer to them as \| and \&.

> For a programmatic example, there's the ever-popular 
> "with-io-redirection" macro family. A proper macro facility in python 
> should let me write:
>         with_output_to_file "filename":
>             code that will be executed
>             with print statement output
>             going into filename
>         code that will have
>         print statement output
>         going to where ever it was
>         going before the macro

In Dylan this might be implemented like:

define macro with-output-to-file
    with-output-to-file (?stream:variable = ?filename:expression)
 => {
      let temp-stream = #f;
      let saved-stream = ?stream;
      block ()
        temp-stream :=
           make(<file-stream>, locator: ?filename,
                direction: #"output");
        let ?stream = temp-stream;
        if (temp-stream)
        end if;
        ?stream := saved-stream;
      end block
end macro with-output-to-file;

... and used as ...

        with-output-to-file (*standard-output* = "filename")
            code that will be executed
            with print statement output
            going into filename
        code that will have
        print statement output
        going to where ever it was
        going before the macro

> Which brings up the primary argument people have against macros. By
> changing the syntax of the language, they make it impossible to
> understand a program by local examination. You have to know what
> macros are in scope and thus might change the programs behavior. Then
> again, the ability to redefine operators does much the same
> thing.

So do:

 - the ability to define functions
 - the ability to assign new values to existing variables

> Which is why I don't buy the "they'll never be added because
> they are inherently evil" argument. The two are equally evil, for the
> same reasons. We've got one. Why not the other?


-- Bruce

More information about the Python-list mailing list