[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