[Python-ideas] Enhance definition of functions

Nick Coghlan ncoghlan at gmail.com
Fri Aug 2 14:48:33 CEST 2013

On 1 August 2013 09:17, Andrew Barnert <abarnert at yahoo.com> wrote:
> But anyway, I think you're mostly agreeing with me. When neither lambda nor def feels right, it's usually not because you really want a multi-line expression, or a multi-line anonymous function, but because you want to get the petty details of the function "out of the way" of the important code, right?

Yeah, I've been grappling with this problem for years, which is why I
have two competing deferred PEPs about it :)

For certain kinds of problem, the natural way to think about them is
as "I want to do X", and as an incidental part of doing X, you need to
define a function that does Y. Sorting, complex comprehensions,
various flavours of event driven programming (especially GUI
programming, where the yield-driven approach of PEP 3156 may not be
appropriate, as well as the low level transport code for PEP 3156
style systems). Lambda isn't a great solution because it embeds all
the complexity of the function directly in the main expression,
obscuring the fact that the overall operation is "do X".

Ruby's block syntax is an elegant solution, but the specific problem
with adapting that to Python is deciding how to spell the forward
reference to the trailing definition. Ruby solves that problem through
a convention (the block is just the last positional argument), but
Python has no such convention - there's a wide variety of signatures
for higher order operations, and a syntax that required new signatures
for everything is no solution at all.

PEP 403 is the approach I dislike least so far, but that's a far cry
from being something I'm willing to propose for inclusion in the
language. The "@in" does hint at the out of order execution nicely,
but it's also a bit too heavy (drawing attention away from the
subsequent simple statement), and as an ordinary name, the forward
reference doesn't quite stand out enough.

PEP 3150 could possibly by improved by having the hidden function
implicitly end with (a more efficient equivalent of) "return
types.SimpleNamespace(**locals())" and introducing "?" as a forward
reference to that result:

    sorted_data = sorted(data, key=?.k) given:
        def k(item):
            return item.attr1, item.attr2

But it's hardly what one could call a *concise* syntax.

On the other hand, it *does* let you do some pretty neat things, like:

    dispatch_table = vars(?) given:
        def command1(*args, **kwds):
        def command2(*args, **kwds):
        def command3(*args, **kwds):

I would also tweak the early binding syntax to require an additional
keyword to make it read more like English:

    seq = []
    for i in range(10):
        seq.append(?.f) given i=i in:
            def f(): return i
    assert [f() for f in seq] == list(range(10))

Using up another precious symbol would be a big call, but it's
starting to feel more like something of sufficient power to justify
new syntax.


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list