[Python-Dev] defmacro (was: Anonymous blocks)
Shane Holloway (IEEE)
shane.holloway at ieee.org
Mon Apr 25 20:23:08 CEST 2005
Michael Chermside wrote:
> Jim Jewett writes:
>
>>As best I can tell, the anonymous blocks are used to take
>>care of boilerplate code without changing the scope -- exactly
>>what macros are used for.
>
>
> Folks, I think that Jim is onto something here.
>
> I've been following this conversation, and it sounds to me as if we
> are stumbling about in the dark, trying to feel our way toward something
> very useful and powerful. I think Jim is right, what we're feeling our
> way toward is macros.
I am very excited about the discussion of blocks. I think they can
potentially address two things that are sticky to express in python
right now. The first is to compress the common try/finally use cases
around resource usage as with files and database commits. The second is
language extensibility, which makes us think of what macros did for Lisp.
Language extensibility has two motivations. First and foremost is to
allow the programmer to express his or her *intent*. The second
motivation is to reuse code and thereby increase productivity. Since
methods already allow us to reuse code, our motivation is to increase
expressivity. What blocks offer is to make Python's suites something a
programmer can work with. Much like using a metaclass putting control
of class details into the programmer's hands. Or decorators allowing us
to modify method semantics. If the uses of decorators tells us
anything, I'm pretty sure there are more potential uses of blocks than
we could shake many sticks at. ;)
So, the question comes back to what are blocks in the language
extensibility case? To me, they would be something very like a code
object returned from the compile method. To this we would need to
attach the globals and locals where the block was from. Then we could
use the normal exec statement to invoke the block whenever needed.
Perhaps we could add a new mode 'block' to allow the ControlFlow
exceptions mentioned elsewhere in the thread. We still need to find a
way to pass arguments to the block so we are not tempted to insert them
in locals and have them magically appear in the namespace. ;)
Personally, I'm rather attached to "as (x, y):" introducing the block.
To conclude, I mocked up some potential examples for your entertainment. ;)
Thanks for your time and consideration!
-Shane Holloway
Interfaces::
def interface(interfaceName, *bases, ***aBlockSuite):
blockGlobals = aBlockSuite.globals().copy()
blockGlobals.update(aBlockSuite.locals())
blockLocals = {}
exec aBlock in blockGlobals, blockLocals
return iterfaceType(interfaceName, bases, blockLocals)
IFoo = interface('IFoo'):
def isFoo(self): pass
IBar = interface('IBar'):
def isBar(self): pass
IBaz = interface('IBaz', IFoo, IBar):
def isBaz(self): pass
Event Suites::
def eventSinksFor(events, ***aBlockSuite):
blockGlobals = aBlockSuite.globals().copy()
blockGlobals.update(aBlockSuite.locals())
blockLocals = {}
exec aBlock in blockGlobals, blockLocals
for name, value in blockLocals.iteritems():
if aBlockSuite.locals().get(name) is value:
continue
if callable(value):
events.addEventFor(name, value)
def debugScene(scene):
eventSinksFor(scene.events):
def onMove(pos):
print "pos:", pos
def onButton(which, state):
print "button:", which, state
def onKey(which, state):
print "key:", which, state
More information about the Python-Dev
mailing list