[Python-Dev] A Hygienic Macro System in Python?

Tim Peters tim.one@comcast.net
Mon, 18 Mar 2002 17:47:05 -0500


[Skip Montanaro]
> (Tom, you gave up way too easily!  Hint for the next time: post to
> comp.lang.python instead of the python-dev mailing list.  There
> are at least 20 or 30 people there who will gladly provide positive
> support for just about any language change proposal.

BTW, there was a long "RFC -- HYGIENIC MACROS IN PYTHON" thread active just
last month on c.l.py.  Here's the head:

    http://aspn.activestate.com/ASPN/Mail/Message/1014711

> ...
> But, since Tom has given up more or less and Tim has diverted the
> thread to his own nefarious uses, I will note that the try/finally
> lock idiom does get tedious.

Indeed, it was the main complaint about Python in one of the papers at the
last conference.

> Using the same argument as "if Guido wanted 'unless' he'd add it
> to the language", I think that if this is important enough, it's
> important enough to add to the language.  I think a "lock" keyword
> would be appropriate:
>
>     lock somelock:
>         do stuff

I think it's more general than that.  A common idiom in C++ is to rely on
that language's strict rules about the lifetime of auto variables, simply
declaring a class instance at block scope, relying on the constructor to get
a resource upon block entry, and the destructor to release it upon block
exit.  This doesn't work in Python because lifetimes aren't specified,
Python doesn't have "block scope" anyway, and even at function scope an
unhandled exception may keep function locals alive.  Lock acquire +
release-no-matter-what fits into the C++ scheme naturally, though.

Python does have block-structured constructs, so the temptation for abuse
hasn't gone away <wink>.

> The biggest problem I found with the try/finally lock idiom was that
> "do stuff" can tend to get long, so the vertical distance between
> lock.acquire() and lock.release() can be substantial.  a lock
> statement/clause/macro would remove the need to worry about that
> visual distance.

The longer I endure life, the more I tend to write this as

lock.acquire()
try:
    one_line_to_call_a_function_that_does_the_real_work()
finally:
    lock.release()

Then it's clear that the try/finally exists *only* to muck with the lock
safely, and the body of the function remains blissfully free of lock
convolutions.