On Mon, Oct 17, 2011 at 10:30 AM, Steven D'Aprano <steve@pearwood.info> wrote:
Either way, out of order execution hurts readability. There's a reason that even mathematicians usually define terms before using them.
I think out of order execution hurts readability *most* of the time, but that not having it is an annoyance most frequently encountered in the form "Python should have multi-line lambdas". When people hit that mental break, they're thinking of a problem in terms of splitting a single operation down into subcomponents rather than building that statement up via a sequence of steps. I was thinking argparse might be a potential use case for the new syntax, and was reminded that it actually has its own somewhat novel approach to provide a 'declarative' interface: it offers methods that return 'incomplete' objects, which you then fill in after the fact. So, for example, instead of constructing a subparser [1] and then adding the whole thing to the parent parser, you instead write code like the following: # create the top-level parser parser = argparse.ArgumentParser(prog='PROG') parser.add_argument('--foo', action='store_true', help='foo help') # Declare that we're going to be adding subparsers subparsers = parser.add_subparsers(help='sub-command help') # One of those subparsers will be for the "a" command parser_a = subparsers.add_parser('a', help='a help') parser_a.add_argument('bar', type=int, help='bar help') # And the other will be for the "b" command parser_b = subparsers.add_parser('b', help='b help') parser_b.add_argument('--baz', choices='XYZ', help='baz help') [1] http://docs.python.org/library/argparse#argparse.ArgumentParser.add_subparse... Note, however, that in order to get a declarative API, argparse has been forced to couple the subparsers to the parent parser - you can't create subparsers as independent objects and only later attach them to the parent parser. If argparse offered such an API today, it wouldn't be declarative any more, since you'd have to completely define a subparser before you could attach it to the parent parser. PEP 3150 would let the API designer have the best of both worlds, allowing subparsers to be accepted as fully defined objects without giving up the ability to have a declarative API: # create the top-level parser parser = argparse.ArgumentParser(prog='PROG') parser.add_argument('--foo', action='store_true', help='foo help') # Add a subparser for the "a" command parser.add_subparser(parse_a) given: parse_a = argparse.ArgumentParser(prog='a') parse_a.add_argument('bar', type=int, help='bar help') # Add a subparser for the "b" command parser.add_subparser(parse_b) given: parse_b = argparse.ArgumentParser(prog='b') parser_b.add_argument('--baz', choices='XYZ', help='baz help') (FWIW, I'm glossing over some complications relating to the way argparse populates 'prog' attributes on subparsers, but hopefully this gives the general idea of what I mean by a declarative API)
But for what it's worth, if we end up with this feature, I agree that it should introduce a new scope, and the "given" syntax is the nicest I've yet seen.
I'm significantly happier with the ideas in PEP 3150 now that I've reframed them in my own head as: "You know that magic fairy dust we already use inside the interpreter to support out of order execution for decorators, comprehensions and generator expressions? Let's give that a syntax and let people create their own declarative APIs" Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia