The problem with significant whitespace is that you can't count on whitespace to be preserved across many common protocols. Text editors will convert spaces to tabs and vice-versa. HTML rendering eats whitespace. Cut-and-paste may or may not preserve whitespace.
Python has had this problem since its inception. If you're editing a Python program in emacs python mode and you hit TAB at the wrong time you can inadvertently change the semantics of your code. And that's just the tip of the iceberg. I'm a big Python fan, but significant whitespace is a bad idea.
> Text editors will convert spaces to tabs and vice-versa.
Get a good text editor?
> HTML rendering eats whitespace.
Except when you tell it not to, of course.
> Python has had this problem since its inception.
problem being mostly encountered by those who never use it, interestingly.
> If you're editing a Python program in emacs python mode and you hit TAB at the wrong time you can inadvertently change the semantics of your code.
So can you if you hit "}" or ";" at the wrong time in a braceful language...
The primary (and as far as I'm concerned the only significant) issue of significant indentation (it's not even significant whitespace) is auto-generated code (which is why Haskell has a braceful syntax and an indentation-based transformation of it), as giving the right contextual indentation to a piece of code may make the code generator much more complex (codegen targetting Python should probably generate python bytecode, rather than generating code).
And to support my claim that significant indentation is not effectively an issue, I will use Haskell: Haskell can be written using both a brace-and-semicolon syntax and an indentation-based one. Both forms are perfectly equivalent and can be translated into one another without loss of information.
I do not remember ever seeing a Haskell piece of code, article, demonstration or example which used braces except when the article was about the braceful syntax or about auto-generated code.
If significant indentation was such a crippling problem, would Haskell users not have coalesced around the "less problematic" braceful syntax?
I use Python a lot. And I encounter these problems often enough for them to be very annoying.
> So can you if you hit "}" or ";" at the wrong time in a braceful language...
The difference is that when you hit "}" or ";" the effect is always the same, it's always visible, and it's always possible to undo by hitting DELETE. If you hit either of those characters N times, you can always undo that by hitting delete N times.
This is not true for the tab key. The effect of hitting TAB depends on the context. Determining whether your last press of the TAB key had an effect or not requires that you remember the previous state, and so undoing the effect (or lack thereof) of hitting TAB requires that you remember the previous state. And if you ever do a block auto-indent at the wrong time you are pretty much hosed.
I had a lot of problems with Python when I was trying to edit code in a variety of different IDEs, text editors, etc.
That was years before I discovered the beauty of Vim (sub in Emacs here, if you like).
For your vimrc:
" Indentdation
set tabstop=2
set shiftwidth=2 softtabstop=2
set smarttab
set expandtab
set smartindent
" Shed light on hidden things
set list
set listchars=tab:»»,trail:•
set wrap
set linebreak
set showbreak=↳
This will use soft-tabs (assert (> spaces tabs)) and expose tabs and trailing spaces on lines using the » and • characters respectively. They show up as a nice, obvious blue in my theme.
Sometimes, this can be annoying for other people's code, who prefer tabs. Easy fix is to `:set nolist` on those buffers.
This also works with file formats that expect tabs, like Makefiles, which have plugins in most Vim distributions that will forcibly type a tab when required. Will be obvious when you see the ». If you ever want to explicitly type a tab, go to insert mode and type ^v<tab> (that is control+v, then press tab). ^v lets you disable custom mappings for the next chord, so instead of <tab> meaning "indent" it will mean "type a damn tab character!"
Meanwhile, our non-technical CEO does some Haml/Sass (both whitespace significant) using TextMate. I had to write some on-save scripts for him to make sure he doesn't submit any trailing whitespace and always ends his files with a trailing newline. grumble grumble
I use emacs and python-mode. This is not an editor issue. It's more fundamental than that. The problem is this:
block:
stmt1
stmt2
stmt3
stmt4
stmt5
If your indenting gets screwed up for ANY reason there is not enough information left to reconstruct it. There is enough information reconstruct the indent at stmt1 (thanks to the colon, which is essentially equivalent to a left curly brace), but not enough to reconstruct the outdent at stmt4. There are many, many ways for indentation to get screwed up.
But to reiterate masklin's point, in C/etc, if your braces get screwed up for ANY reason there is not enough information left to reconstruct them. So what's the difference between meaningful braces and meaningful indentation?
To that you replied that the output of the Tab key depends on context, and implied that in your editor(s), sometimes the result of the Tab is invisible, and/or cannot be reversed by hitting Delete (or Backspace). And snprbob86 pointed out that in his/her editor (and mine), this isn't a problem. Tab never does anything invisible, and it's always reversible with Backspace. So what's the problem?
And although I assume you noticed this too, just to be clear and err on the side of explicitness, it seems to me that that there're two things going on here. One half is arguing about whether or not there's a fundamental problem with significant indentation that is not present in languages without significant indentation, and the other is an attempt to solve non-fundamental problems that others might have (e.g. complicated state in tabs, possibly due to using a poor editor).
> if your braces get screwed up for ANY reason there is not enough information left to reconstruct them
That's not necessarily true. If my code is indented, then I can reconstruct the braces from the indentation. Also, it's a lot easier to inadvertently screw up whitespace than a brace because there are so many more things out there in the digital world (HTML, autoindent) that muck around with whitespace than things that muck around with braces.
The right answer is to SPECIFY block structure using braces (or something equivalent), but then RENDER the block structure using (automatically generated) indentation. It's perfectly fine for the compiler to complain if they don't match. This is one case where redundancy is a feature, not a bug.
If you hate braces and love whitespace so much, why are you not urging Guido to get rid of the colon? It's essentially equivalent to an open brace. Why is an open brace more pythonic than a close brace?
> using a poor editor
I use emacs, but just to see if maybe I'm missing something I fired up vim and tried editing some Python code. AFAICT vim (at least out of the box on Snow Leopard) is not aware of Python syntax at all.
Presumably if its a problem, the accidental change in indentation changed the code to a wrong form, rather than a form that can't be parsed (i.e. unindenting in the middle of a block, which will just cause easy-to-identify indentation errors).
Think about the same situation in, say, C. Now, your program still compiles correctly - but people read it as doing something differently. I'd argue that its worse to accidentally disconnect a reader's interpretation from a compiler's than to change both of them to something that's logically incorrect.
The ironic thing about Python is that it actually does have an open-brace. It's the colon. The compiler can tell that this:
def foo():
baz()
is syntactically incorrect. And if you tab the second line, auto-indent can do the Right Thing. The screw case is this:
def foo():
if baz:
bar()
bing()
boff()
If you auto-indent the last line, it will quietly change the semantics of your program. That's bad.
I always end my blocks with a PASS statement (or a return), i.e.:
def foo():
if baz:
bar()
bing()
pass
boff()
return
If you do this, then auto-indent will always do the Right Thing. This is particularly beneficial if you want to take a big block of code and wrap in an an outer block. I can add two lines to the above code:
def foo():
while snoz: <--
if baz:
bar()
bing()
pass
boff()
pass <--
return
Then I can just auto-indent the whole thing and be confident that the result will be correct.
Contrast this with the traditional method where you have to manually re-indent your code. If you accidentally select the wrong region to re-indent you can change the semantics of the code in a way that loses the information about what the semantics should have been. The only way to recover from this is to manually reconstruct the correct semantics. It may not happen very often, but when it does it's a colossal PITA. (Entering those examples was a colossal PITA too.)
Wait, so you reconstruct the end delimiter using pass? That's one of the least-pythonic things I've ever seen. I really don't see how this could end up being a problem - doing a block indent shouldn't be this difficult.
> Wait, so you reconstruct the end delimiter using pass?
Yes.
> That's one of the least-pythonic things I've ever seen.
What can I say? It works.
> I really don't see how this could end up being a problem
Do you use emacs? Open up two windows, each with an emacs editing some python code in python mode. Cut and paste some code from one window into the other.
I don't use emacs, but I use vim, and I suspect I've seen the problem you're talking about. Its the one where auto-indent puts extra indentation in pasted code? This is a problem of not knowing how to use your editor. For example, in vim I either open files in tabs (and use the vim yank buffer/clipboard) in the same editor, or go into `paste` mode to paste from the OS clipboard. I'm not sure what the solution is in emacs, but I guarantee there is one.
Python has had this problem since its inception. If you're editing a Python program in emacs python mode and you hit TAB at the wrong time you can inadvertently change the semantics of your code. And that's just the tip of the iceberg. I'm a big Python fan, but significant whitespace is a bad idea.