On 1 August 2013 09:17, Andrew Barnert
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. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia