Why whitespace denotation of blocks doesn't work.

Thaddeus L. Olczyk olczyk at interaccess.com
Sat Jun 17 03:49:43 EDT 2000


After using Python for a while I've come to the conclusion that
using whitespaces to determine the begining and ending of blocks
is bad for three reasons.

Before I list those three reasons let me make two points. People say
that the indentation requirements don't matter because you generally
indent the same way. That may be true, but do you think it is a good
idea to make conventions requirements ( remember that conventions
start flame wars )? The second is that modern editors with good
indentation rules ( like emac's python mode ) make indentation based
coding easy. The thing is that by doing this you are abrogating
control flow to the editor. When it was the editor indenting code
which was well defined then there was no problem. By having
the code depend on indentation, and the editor do the indentation
for you, you give the editor responsiblity in how the code will flow.

Now on to my points.
1) The first is rather stylistic and may not appeal to most, but I
have often found it useful. When debugging code I often put in
code to help me figure out whats happening. I also avoid indenting
such code so that it easy to remember where it is later when I want to
take it out. An example ( assuming I use begin and end to denote
blocks ):

def Average():
begin 
      sum=0
print "number of numbers=",len(numbers) #illegal
i=0
      for n in  numbers:
      begin
print "n=", n #illegal
            sum=sum+n
print "sum=",sum #illegal
 i=i+1                     #illegal
if sum>MaxNumber*I:#illegal
begin                     #illegal    
  print "sum is too large"#illegal
end                        #illegal
     end
     if len(numbers)!=0:
     begin
        return sum/len(numbers) 
     end
     return 0
end

You can immediately see code that you used for debugging and remove
it. However right now writing code that way makes it illegal.

2) You can easily insert a tab introducing a bug.  Consider the
following code ( similar to a bug I recently fixed ):

def FindInvoice(idnum): 
      for invoice in invoices:
            if invoice.id=idnum:
	      return invoice
            return None # should be indented one less tab.

....

for lines in file.readline():
     idnum=lines[:6]
     invoice=FindInvoice(idnum)
     if not invoice:
              invoice=InvoiceClass(idnum)
	 invoices.append(invoice)
....
Initially the line in error was indented correctly, but someplace
along the line the extra tab was introduced. A lot of effort then had
to go in to finding this bug. With begin...end or braces this is less
likely to happen.

3) Finally. Python is a language where it is almost easy to write
extensible programs. To illistrate what I mean consider this example
of a python program I recently wrote:
There is a C++ project which involves many project files and workspace
files ( the project files are roughly equivalent to makefiles, the
workspace files primarily are used to couple projects and define
dependencies ). Version 1 simply read all the project files and 
generated a call to compile each one with all different configuartions
(debug , release, alpha, beta etc..) . Since this built everything
even if it was already built, and since this had to be run several
times ( sometimes compiles would fail because a project that the
present project was dependent on wasn't compiled ), I made version
two. Version 2 read the workspace file and organised the projects
into workspaces. Version 3 passed the string to a second script so
that the second script could figure out if this was something that
should be built ( for example whether a standard Win32 build or a
WinCE build should be done ). Version 4 tracked dependencies more
carefully ( it did a topological sort and orgainsied the build
according to it ). Since the core stuff should be built first, I had
to find out a way to figure out which was core. I used a definition of
the core stuff is the stuff with the longest chain of dependencies.
That was Version 5.

As you can see I started with a simple program and made it more
complex as I went on.  That's what I mean by extendible. Python is
almost good at it. Almost. But that damned code indentation dependence
backs its ugly head. In the process of extending code, I have to move
blocks of code around. Sometimes put it in a loop, sometimes add an if
clause to the top. Sometimes extract code into a subroutine. That
means that I have to reindent the block. So as I reindent I have to
try to remember how the indenting went. Something I stink at. 
Emacs also doesn't reindent correctly. So I have to go through the
code, and try to figure out how it works. This distracts from my 
rewrite ( this also applies to refactorings ). I would rather think
about how new code is supposed to work rather than how old code
is supposed to work.

Anyway I hope this causes TPTB to think about how blocks should be
handled in Pyhton 3000.








More information about the Python-list mailing list