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

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to