[Python-ideas] An Alternate Suite Delineation Syntax For Python? (was Re: [Python-Dev] [PATCH] Adding braces to __future__)

Steven D'Aprano steve at pearwood.info
Sun Dec 11 02:55:51 CET 2011


Mike Meyer wrote:

> Since you sent it to Python-ideas, I'm going to assume you were at
> least semi-serious. So let me add the use case I came up with while
> reading the original post, also often seen in template languages:
> 
>     Writing code to generate python.
> 
> With significant whitespace, you have to keep explicit track of the
> current nesting level in order to generate the appropriate
> indent. With real delimiters, you can drop that. Compare:

That's hardly an onerous requirement. As you show, the two code snippets are 
almost identical, except that the indent version takes an explicit level 
argument, while your braces version neglects to close suites at all. A fair 
comparison should show the close-suite code, even if it is only a single line.

>     def generate(self):
>         yield '{keyword} {expr}{:'.format(keyword=self.name,
>                                          expr=self.expresion)
>         for s in self.suite:
> 	    for l in s.generate():
> 	        yield l

I guess you would need to yield '}' after the outer for loop.

> With:
> 
>     def generate(self, level):
>         yield '{0}{keyword} {expr}:'.format(' ' * level,
>                                             keyword=self.name,
>                                             expr=self.expresion)
>         for s in self.suite:
>        	    for l in s.generate(level + 1):
> 	    	yield l
> 
> 
> A minor improvement in just that one method, but it will show up in
> every generate method of every class, making it significant in total.

I wouldn't use the term "minor improvement" so much as "trivial difference".

But even if I grant that it is an improvement, how many generate methods do 
you expect there to be? Presumably most of them will inherit their generate 
method from one or two parent classes. Even if every block keyword gets an 
independent copy in violation of DRY, there's still fewer than a dozen classes 
needed: def class for while if elif else try except finally with. So the total 
significance is still likely to be small.

But wait... now you have your code generator, which generates ugly, unreadable 
code. Code needs to be read more often than written, even generated code, so 
now you need a code beautifier to reformat it using indentation for the human 
reader. Which means keeping track of the indent level. You're right back where 
you started, only worse, because now you have to parse the generated code to 
reformat it, instead of formatting it correctly the first time. So to save a 
dozen lines in your code generator, you end up with an extra hundred lines in 
a code beautifier. A classic example of code pessimation (of LOC rather than 
speed in this case).

I think it is suggestive that we will need to warn people not to use this 
hypothetical syntax. As Nick wrote:

>> However, that's also something that can be addressed by style guides -
>> if people are using the embedded syntax when the indented syntax would
>> work fine, the problem isn't really due to the embedded syntax, it's
>> due to people not caring about maintainability.

People who don't care about maintainability don't care about readability and 
they certainly don't read style guides unless they are forced to.

> I think not. As someone else observed, Haskell has both options
> available - and the rules for the indented version are a lot less
> straightforward than they are in Python (at least I haven't seen as
> clean a statement of them). About the only use of the delimited
> version in real code is turning a short suite into a one-line suite.

When you defend a feature on the basis that "people will hardly ever use it, 
except for trivial pieces of code that don't need it", that speaks volumes.




-- 
Steven



More information about the Python-ideas mailing list