Guido van Rossum wrote:
Why not just introduce macros?
Because I've been using Python for 15 years without needing them? Sorry, but "why not add feature X" is exactly what we're trying to AVOID here. You've got to come up with some really good use cases before we add new features. "I want macros" just doesn't cut it.
I had a use-case recently which could be done using macros. I'll let you all decide whether it would be "better" with macros or not. ;)
My poor-man's ORM uses descriptors to handle the properties of domain objects, a lot of which need custom triggers, constraint-checking, notifications, etc. The base class has:
def __set__(self, unit, value): if self.coerce: value = self.coerce(unit, value) oldvalue = unit._properties[self.key] if oldvalue != value: unit._properties[self.key] = value
At one time, I had something like:
def __set__(self, unit, value): if self.coerce: value = self.coerce(unit, value) oldvalue = unit._properties[self.key] if oldvalue != value: if self.pre: self.pre(unit, value) unit._properties[self.key] = value if self.post: self.post(unit, value)
...to run pre- and post-triggers. But that became unwieldy recently when one of my post functions depended upon calculations inside the corresponding pre function.
So currently, all subclasses just override __set__, which leads to a *lot* of duplication of code. If I could write the base class' __set__ to call "macros" like this:
def __set__(self, unit, value): self.begin() if self.coerce: value = self.coerce(unit, value) oldvalue = unit._properties[self.key] if oldvalue != value: self.pre() unit._properties[self.key] = value self.post() self.end()
defmacro begin: pass
defmacro pre: pass
defmacro post: pass
defmacro end: pass
...(which would require macro-blocks which were decidedly *not* anonymous) then I could more cleanly write a subclass with additional "macro" methods:
defmacro pre: old_children = self.children()
defmacro post: for child in self.children: if child not in old_children: notify_somebody("New child %s" % child)
Notice that the "old_children" local gets injected into the namespace of __set__ (the caller) when "pre" is executed, and is available inside of "post". The "self" name doesn't need to be rebound, either, since it is also available in __set__'s local scope. We also avoid all of the overhead of separate frames.
The above is quite ugly written with callbacks (due to excessive argument passing), and is currently fragile when overriding __set__ (due to duplicated code).
I'm sure there are other cases with both 1) a relatively invariant series of statements and 2) complicated extensions of that series. Of course, you can do the above with compile() and exec. Maybe I'm just averse to code within strings.
Some ideas. Now tear 'em apart. :)
Robert Brewer MIS Amor Ministries email@example.com