No macros in Python

Lulu of the Lotus-Eaters mertz at gnosis.cx
Mon Dec 16 15:36:18 EST 2002


|>     def with_output_to_file(fname, stmts):
|>         import sys
|>         orig = sys.stdout
|>         sys.stdout = open(fname,'w')
|>         for stmt in stmts: exec stmt
|>         sys.stdout = orig

Mike Meyer <mwm at mired.org> wrote previously:
|First of all, you've got three bugs(*), which is why this kind of
|thing should be bundled into a macro instead of forcing every
|programmer to write it themselves.

Macros can have bugs too, just as easily as functions can.  Stipulating
you were correct about bugs in this *library* function, that would just
mean that the bugs should be fixed.  It doesn't at all speak to the
macro/function issue.

|*) 1: not closing the file. 2: not handling exceptions in the
|statement list. 3: evaluating the statements in the context of
|with_output_to_file instead of in the context of the invoking
|function. All these can be fixed.

None of the suggested bugs, FWIW, are bugs.  The normal way of closing a
file in Python is letting reference count fall to zero.  That's exactly
what the code does (and almost all my code, and most everyone else's).
Maybe Lisp programmers do it differently, but my example was in Python.

I don't handle exceptions because I had no idea that the hypothetical
macro included exception handling.  If that handling is part of the
spec, I can add it.

OK.. the context of evaluation was an under-specification.  I guess I
cannot call it a -feature-, but neither is it a bug unless there is some
spec that says what is supposed to happen.  But see another recent post
of mine for details on grabbing the locals and globals of a calling
frame.  If that's the spec, I'd be happy to do it.

|you've hidden the difference in the format of the statement list.

I wasn't sure whether the closer analogy to your hypothetical macro
would be to pass one statement, a list of statements, or just a list of
expressions to print out.  Tell me the spec, and the function is
straightforward.

|Third, what you've written is a macro.

Nope... it's a function.  That's the whole point, after all.  Unlike a
macro, I ENCAPSULATE the set of actions, and don't change the syntax of
the language.

I agree that macros can be somewhat clumsy ways of expressing
functions... but there is a difference.

|It's someone potentially mucking with the meaning of things
|you "know" what mean. But that's bad practice.
|I can define my own version of len...

I know.  I didn't say you couldn't do anything bad in Python.  Just that
you can do fewer bad things because of the macro-free quality.

|BTW, if you really want a ternary operator, you can do it in
|Python. It's just really ugly because python doesn't have macros.

Nope... you cannot have a ternary OPERATOR in Python (unless Guido adds
one to 3.0).  You can accomplish the same effect.  An ugly way is:

    val = ((pred and [foo]) or [bar])[0]

A prettier way is:

    if pred: val = foo
    else:    val = bar

But neither one is an operator (the first uses three operators, the
latter, two statements).

Yours, Lulu...

--
Keeping medicines from the bloodstreams of the sick; food from the bellies
of the hungry; books from the hands of the uneducated; technology from the
underdeveloped; and putting advocates of freedom in prisons.  Intellectual
property is to the 21st century what the slave trade was to the 16th.




More information about the Python-list mailing list