A modest indentation proposal

Erann Gat gat at jpl.nasa.gov
Fri Nov 30 17:19:02 CET 2001


In article <3C0773C2.A12D0BAC at pacific.net.hk>, Bernie
<bernie at pacific.net.hk> wrote:

> Erann, I think you find the indentation annoying because you choose 2 spaces 
> as your tab size, hence making the block not as apparent as it could 
> be.  Try four spaces, or use Tools/Scripts/pindent.py if you really cannot 
> stand it.

No, that's not it.  Let me explain that remark, but first let me say the
following:

  *** I am not suggesting the semicolon rule to replace syntactically
  *** significant indentation, but merely to augment it.

Here's what I find annoying:

Consider the following code:

biff()        # Line 0
for x in l:   # Line 1
  foo()       # Line 2
  baz()       # Line 3
bar()         # Line 4

When I use python-mode in emacs the editor will automatically indent for
me after line 1.  In fact, if I screw up the indentation accidentally,
emacs can automatically restore it in the above example except for line
4.  The reason it can do that is because of the colon at the end of line
1.  That colon is actually redundant.  It tells you unambiguously that the
next line must be indented or you have a syntax error.  I consider this
redundancy, and emacs's resulting ability to automatically reconstruct the
indentation to be a feature.

The reason emacs can't restore the indentation on line 4 is that there is
no such redundant information for emacs to use to determine where a block
ends.  People have suggested a convention like:


biff()        # Line 0
for x in l:   # Line 1
  foo()       # Line 2
  baz()       # Line 3
# end for
bar()         # Line 4

What I am suggesting is no different, except that instead of "# end for" I
want to use ";".  The reason is simple: it's less typing, and it's easier
to modify emacs python-mode to detect a trailing semicolon than an
end-block comment.

There is in fact already a hack for this.  I could write:


biff()        # Line 0
for x in l:   # Line 1
  foo()       # Line 2
  baz()       # Line 3
  pass
bar()         # Line 4


and emacs will re-indent line 4 properly.  RETURN also serves to
unambiguously mark the end of a block.  But IMO putting in pass statements
all over the place to mark the end of blocks is really ugly.

I'd also like to respond to a few other comments:

* Steve Lamb:

> > It also IMO makes the language unsuitable for mission-critical applications.
> > It's just too easy to screw up indentation (particularly when cutting and
> > pasting large blocks of code) without realizing it.

>  Hogwash, plain and simple.  Either you know it because it is visually
> different or you know it when you test the application and it fails
> spectacularly.  You /do/ test your mission-critical applications, don't you?

Yes, of course we test our mission critical applications.  Please extend
me the courtesy of not immediately assuming I'm an idiot just because I
make a proposal that you don't like.  But testing is actually a very
ineffective way of insuring that software works, particularly
mission-critical software.  For one thing, it's not possible to test
spacecraft software under field conditions until the spacecraft is
launched, and by then it may be too late.  For another, many bugs,
particularly in real-time multithreaded systems, are probabilistic, and so
even if your tests work perfectly that alone does not provide a lot of
confidence that your software is in fact correct.

* Skip Montaro:
> As has been demonstrated many a time, you're more likely to screw up a C
> block by omitting braces:
>
>    if (cond)
>        x = 1;
>        y = 1;

Yes, this is exactly my point.  You can look at the above code and tell
there's something wrong because the braces and indentation provide
redundant information in C.

* Skip:
> In fact, it's such an insidious
> problem in C code that many groups mandate that all blocks use { & }, even
> for one-statement blocks.

Yes, and the situation in Python is that the language mandates an
open-brace (or it's equivalent, the colon) and doesn't provide a
close-brace even as an option.

> In Python, if it looks right, it is right.

No, that's not true.  Consider the following two alternative code fragments:

if x:
  foo()
baz()

if x:
  foo()
  baz()

They both look right, but they can't both be right.

* Skip:
>    Erann> This convention is 100% backwards-compatible with current
>    Erann> practice, that is, code written using this convention runs with
>    Erann> no problems in Python as it currently stands.
>
>Not it's not.  Semicolons can legitimately be used to end a statement now.

Well, that's actually what I meant by "backwards compatible."  I know that
semicolons can be used at the end of statements, but at the moment doing
so is a no-op.  (All it does is betray you as still thinking in C/Java.) 
I want to take syntax that is currently legal but useless and make it
useful.

Look, the reason I made this proposal is not that I want to come in and
tell the Python community that syntactically significant indentation is
all screwed up and should be discarded.  The reason is that I want to sell
people at JPL on the idea of using Python to write mission-critical
software, and the people I'm trying to sell are raising this objection.  I
can counter this objection, but only three-quarters of the way.  I can
point out that Python already provides enough redundant information to
reconstruct corrupted indentation at the beginning of blocks, but not at
the end.  To reconstruct it at the end of blocks all I can offer is my
"pass/return" hack.  I'd really like to be able to offer a standard
syntactic convention that is endorsed by the Python community.  That would
make Python a lot easier to sell.

So lighten up, folks.  We're on the same side.

Erann Gat
gat at jpl.nasa.gov



More information about the Python-list mailing list