Python-like tabs instead of curley brackets?

Chris Nicholson-Sauls ibisbasenji at
Mon Oct 30 06:50:55 PST 2006

Nils Hensel wrote:
> Chris Nicholson-Sauls schrieb:
>>You gave an example yourself at the bottom of your post, when you
>>mentioned bottom-controlled loops.  Although Ruby's until() loop is a
>>good example of how to overcome such things, at least a little.  Then
>>again, Ruby isn't a good example for this discussion... I find that Ruby
>>is almost mind-bogglingly expressive, which is nice, but makes it
>>difficult to compare with.
> "until" is exactly what I use to overcome this but I don't know if
> that's anything like Ruby's for I don't know Ruby.
> You still have to know that it's bottom-controlled, though. :(

In Ruby the statement "until (x == y)" is the same as "while (x != y)", which when coupled 
with some cut logic inversion, can pull off the trick.  I don't think I ever used the 
Python equivelant, but I'm sure its likely the same.

>>We would sacrifice it by giving whitespace meaning, thereby changing the
>>priorities of operators and other symbols in parsing... or in short,
>>changing this one piece of syntax changes the case-usability of the rest
>>of the syntax.
> This problem doesn't arise when you only give meaning to leading
> whitespace and leave everything else as it is, except for the "one line
> = one statement" rule (which is true for most cases).

That is true, the comment on only giving meaning to the indentation, and not to internal 
spaces.  And it would clarify most cases.  However, unfortunately I have pleanty of "one 
line != one statement" code, due to using API's (such as Windows *shudder*) that expect 
arduous function arguments, and/or due to complex logic/bool expressions that are easier 
for me to read when spread across lines.  I suppose a new indentation level in the middle 
of a statement would be enough to represent continuation, but then we introduce the new 
requirement of a statement terminator in the general case; re-introducing the 
"redundancies" that we had tossed.

Its either that \
or prefixing lines with \
those bloody back-slashes \
like some platforms I \
won't mention by name.  ;)

>>>>source portability,
>>I might like quad-spaces, you might like hard tabs, "Bob" might like
>>2-space, Walter likes 8-space, etc.  Sure, editors can apply whatever
>>tabbing rules one likes, but then only if one sticks to hard tabs.  And
>>heaven forbid if other whitespace starts getting meanings, then it can
>>become "truly" non-portable if different OS's have different
>>representations (an example is the newline, which is \n on some systems
>>and \r\n on others).
> You're right: tabs are evil. ;-)
> But programmers shouldn't use them anyway IMO because they make code
> unreadable regardless of language.

Well, we're agreed on that.  Which is saying something, as I used to be a hard-tabs nut.

>>>>useful niche  features such as anonymous scopes,
>>>Not if you have a keyword for that.
>>One might argue, then they aren't really anonymous.  ;)  That's
>>tongue-in-cheek, but the point is sound.  Given these two examples:
>># void main () {
>>#   doStuff;
>>#   { auto Foo f = new Foo;
>>#     doOtherStuff;
>>#   }
>>#   doFinalStuff;
>># }
>># void main ()
>>#   doStuff
>>#     auto Foo f = new Foo
>>#     doOtherStuff
>>#   doFinalStuff
>>Yes I do admit that the second example is two lines shorter.  However, a
>>line with just a '}' on it is hardly worth counting, and also I find the
>>braces immensely meaningful.  They make it very clear that I'm
>>introducing a new scope, whereas in the other case my "scope" might be
>>mistaken as a body block to the 'doStuff' symbol.
> you could use a keyword like "scope". For example:
> # void main ()
> #   doStuff
> #   scope
> #     auto Foo f = new Foo
> #     doOtherStuff
> #   doFinalStuff

But scope already has a meaning... ;)

> That's the way indentation should work anyway, starting a block with a
> keyword, like you would usually do in D anyway. So
> # if (condition)
> # {
> #   do_work();
> # }
> becomes
> # if condition
> #   do_work()

My style would have that opening brace on the line with the if() statement, so dropping 
the {}'s really only shaved a single line off -- and never would remove any more than 
that.  The one advantage this area does give to indentation-syntax is that it becomes 
easier to add debugging/etc code to pre-written one-line blocks that you hadn't considered 
for extra code.  Personally, I just make a point of never leaving the {}'s out, and this 
never effects me.

>>It also leaves me hanging as to whether or not main() is actually
>>closed at this point.
> Experience tells me you may trust it to be closed. I've never had any
> difficulties with that. I believe you would soon feel the same, it's a
> proven technique.

My eyes see nothing but more code after main(), therefore it takes me a while to register 
that main() is no longer going on, but that this code is something else.  The fact that 
the whitespace is different simply doesn't register for me.  I guess I just spend far too 
much time in things where I mostly (or even completely) ignore spaces.

>>How do you suppose we should do D's
>>design-by-contract functions?  The only thing I can think of would be:
>>// current
>># void foo (int x)
>># in {
>>#   blah
>># }
>># out {
>>#   blah
>># }
>># body {
>>#   blah
>># }
>># unittest {
>>#   blah
>># }
>>// new
>># void foo (int x)
>>#   in:
>>#     blah
>>#   out:
>>#     blah
>>#   body:
>>#     blah
>># unittest:
>>#   blah
> You may omit the ':'. It's not needed.

I know it isn't technically, but I liked the extra decoration.  Oh well, just me thinking 
in terms of symbols again I suppose.

>>Its cute, but one false move and I've got a dangling statement if I miss
>>one little space character.
> But the same is true if you accidentally erase a closing brace. You can
> easily screw up C-style syntax as well, trust me on that one ;-)

I can't imagine why I would erase braces unless I was erasing the entire statement 
associated with them (they're always the first thing I type as well, right after the 
statement name and its parenthesis).  The difference is vital, however.  If I am working 
on some code, and I accidentally put 7 spaces where there should be 8, I may or may not 
realize something is amiss.  I sit and drum on Undo/Redo trying to spot something, and it 
just isn't there.

On the other hand, if I somehow manage to erase or overwrite a brace character, as I tap 
on Undo/Redo I immediately notice a brace is appearing/disappearing, so I stick it back in 
where it belongs.  Or, I can simply scan my cursor over the chunk of code I was editing, 
and the pair-highlighting feature makes it clear to me that this delimiter (parenthesis, 
bracket, or brace) has no partner; better give it one.

>>I know, I'm being anal again.  But its
>>something I just don't feel I should have to worry about.  In this kind
>>of syntax, I find I actually end up spending more time worrying about
>>alignment, etc, when I'm just trying to get a rought draft implemented,
>>rather than doing it later during cleanup/tweaking.
> I believe one crosses from worrying about alignment to just using
> alignment fairly quickly. Having to end up with readable code is a bonus
> IMO not a disadvantage.

In the general case, you are right.  But, what if I complete that draft of code, only to 
find that I've made a major mistake, and must scrap the entire thing and quickly re-write? 
  If I was having to pretty-format the whole way, then I've wasted time.

>>>>and enter the world of ambiguous nesting levels.
>>>In what way are they ambiguous?
>>See my previous example, and see the plethora of other discussions about
> I must confess I still don't see any ambiguity. To me it's pretty clear
> what opened the nesting level I'm currently in. I just have to look back
> to the last line with less indentation to see that.
>>>>Python and D are two different galaxies.
>>>I'd say: "different tools, same shed".
>>Fair enough, except that they still have niches they fulfill that the
>>other doesn't.  As I've said before, I have (and very occasionally still
>>do) worked in Python, because at the time it seemed the most
>>straight-forward way to solve a specific problem.
> I agree that Python and D are best at different uses, but that is not
> due to different parsing. It's because D is very much less dynamic than
> Python at runtime at the increase of speed.
> Both approaches are valuable in different occasions, but both could be
> handled using the same syntax constructs.
>>>>Scope-by-indentation is a good choice in that case, where the speed
>>>>and blindness of parsing are paramount.  It would be a massacre for D.
>>>That is just not true. Scope indentation usually just results in an
>>>openly visible code structure and shorter source code because of the
>>>lack of unnecessary delimiter syntax.
>>What is more "openly visible" than open-close symbols, such as {}'s?
> A hint may be that there is no such thing as an "obfuscated
> Python"-contest as there is for C. You can write a whole C-program in
> one line if you are either an aesthetic pervert or just full of hate for
> your co-workers. ;-)
> Just think about the different conventions where to but the opening
> curly brace. There is no such choice in Python. You only agree on the
> depth of indentation you use.
> And years of working on OPC (other people's code ;-) have taught me the
> importance of writing easily understandable code. I would go as far as
> to say the best language would be one that forces you to comment your
> code as well as making it work.

The caveat is, 1) there are really only two choices on where to put the brace -- same line 
or next line -- and 2) one can quite easily run "obfuscated" C code through a dummy parser 
and casually read the properly-formatted output copy.

Also, I seriously doubt anybody uses things such as may be found in "obfuscation" contests 
in legitimate real-world code.  If they do, then they deserve to be one very, very lonely 
programmer.  ;)

>>>I've written a preprocessor for C-style languages
>>Then you have what you want.  ;)
> Yes, I do.
> Don't get me wrong. I'm not advocating switching from C-style to
> Python-style syntax for D. I also believe that to be a mistake at this time.
> It was just that there seemed to be a lot of unjustified Python-bashing
> going on (not from you though, I replied to your post because you were
> the only one actually giving arguments :)
> All I wanted to point out was that Python-style syntax does not prevent
> you from ending up with a powerful programming language such as D.
>>I'm not concerned with how short the
>>output files are, but rather with how well I can 1) express what I want
>>with absolute clarity,
> Same here, though I enjoy having shorter source files - less bugs and
> easier to grasp.
> I just want to do away with the unnecessary stuff like most parentheses,
> braces, semi-colons and the like.

In the BovisMOO language, which I have full control over, there are certain cases where 
one can do away with some things (for example the expression ' :name ' is the same as ' 
$This:name() ').  But I actually find that trying to become completely independant of 
symbols/operators in a language design is quite simply beyond me.  Maybe just not enough 
of the right kind of experience.

> Actually some things are even longer to write in my preprocessor for the
> sake of expressiveness, e.g. logical operators ('and' instead of '&&').
>>and 2) format the code to suit my own aesthetics
>>so that I can understand it later with ease.
> Which is great if you're the only one working on your code. Otherwise
> you have to hope for your co-workers to share the same aesthetics. :)

They'd better.  ;)  Generally though, at least being consistant in one's formatting is 
enough.  For example, I am completely baffled by Kris' coding style used in Mango, and yet 
I can read Mango code with no difficulty, because his style is consistant enough my eyes 
just "learn" it as they go.

-- Chris Nicholson-Sauls

More information about the Digitalmars-d mailing list