78 comments

[ 2.4 ms ] story [ 87.9 ms ] thread
This is an interesting exercise, but most of the suggestions on the page are just cosmetic, and do not address the fundamental challenge of C++ - perhaps the biggest divergence between Python and C++:

A core design principle of C++ is that you do not pay (performance-wise) for what you don't use. This leads to all sorts of nasty things like object slicing, law of big 3, template preprocessor hell just to get pseudo-generics.

A core design principle of Python is that you should pay the minimum cognitive burden for what you are not using. Don't care to customize object dispatch? Then you don't need to know about descriptors and __slots__ just to write a simple class.

No amount of syntactic cargo culting is going to bridge this gap. The whitespace and lack of semicolons is not why people embrace Python. Just as removing integer types and sensible scoping from C++ won't make it Javascript, replacing braces with tabs is not going to make it Python.

This is obviously not trying to address divergence between Python and C++. Stop attacking strawmen.

Nobody sane would imagine C++ in Python syntax would appeal to Python programmers. On the other hand, C++ in Python syntax would appeal to C++ programmers who prefer Python syntax to C++ syntax. I am one of them, and this is a good try.

I disagree that greatly reducing the mental overhead of visual processing is merely a cosmetic change. This may just be an issue of taste, or familiarity, but I greatly prefer not presenting the same information twice. Once with characters and the second time with indentation. Why not just indentation? Also it forces people to make all hierarchical code blocks immediately visible, instead of being free to put them anywhere they like.
This is the exact opposite of what I want in C++.

The use of characters to clearly delineate code sections and scope is a strong benefit of C++ over these other languages. They're not a "source of errors" - they allow a competent programmer the opportunity to quickly reason about the structure of the code. If vertical compression is an issue - get a bigger monitor or an IDE that allows for code hiding.

It is also far better to have a "oops, I missed a brace" error that your compiler/IDE catches, versus a "man, why does my program keep seg faulting unexpectedly" error that takes hours to track down since you missed a single tab somewhere.

I'm not sure what your complaint is here. With whitespace sensitivity, "oops, I missed a brace" and "oops, I missed a tab" is exactly the same. Your compiler/IDE would catch it, just as it would any other syntax error. The difference (arguably) is that it's easier to spot (because that's how humans read code).

I would argue that whitespace sensitivity makes those kinds of errors less likely, not more. Curly braces everywhere lead to a lot of visual noise, and can obscure what the code is doing. Consider the classic C syntax error:

    if (foo > bar) 
        printf("Hey!\n");
        return foo;
    return bar;
With whitespace sensitivity, this would do what you think it would. With curly braces, it's misleading.
Whitespace sensitivity also introduces some similar problems. For example, if the printf is indented with spaces and the return foo is indented with tabs, the return will be put outside the if, even though it looks like its inside.

TBH, the real problem with C is not the braces - its that braces are optional.

>For example, if the printf is indented with spaces and the return foo is indented with tabs, the return will be put outside the if, even though it looks like its inside.

Python 3 deals with this by throwing a warning about inconsistent use of tabs and spaces before it even finishes parsing the file (so basically before runtime). There's no reason why any other language can't do the same.

(comment deleted)
I think tabs vs spaces problem is silly and nobody should be using tabs. Editor should be showing tabs in red and asking the user to clean them up.
I switched from tabs to spaces about a decade ago and I've never regretted it. I seldom find files written by crazy people who think 8 spaces is a viable tab width anymore so I can pretty much adjust to whatever nice 2 space or wasteful 4 space width the original file authors used.

Back in the 1970s, I chose tabs to save bytes in my text files. Today I feel like I can afford the extravagance.

I think the tabs vs spaces problem is silly and nobody should be using spaces[1]. Compilers should treat leading spaces as a syntax error.

Clearly we both can't be pleased. ;)

[1] Except in Lisp.

Every social problem has a simple, rational solution: forbid (and strongly enforce it) anybody making, owning, or talking about, any of the following:

- editors that allow one to set tab width different from 1.

- editors, compilers, and OSes that distinguish tabs from spaces in any way (display of invisible characters, search).

- revision control systems that do not randomly replace spaces by tabs and vice versa in all text files.

If you used our coding style (haskell-ish) you would have no problems with tabs. Keep stuff logically towards the left to make quick scanning easier.
Most languages that are whitespace sensitive don't actually allow you to mix indentation. In fact, Python 2 will give you an error saying that a particular line doesn't match indentation level if it's a different number of spaces and 3 will give you a warning (and since warnings can be made into errors...).
> With whitespace sensitivity, "oops, I missed a brace" and "oops, I missed a tab" is exactly the same.

No. There are two braces per block and as long as you are consistent and always use braces even for single-statement if(){}, you need to miss two braces for equivalence with missing one tab. You also get the benefit that the editor can trivially re-indent your code without actually changing its meaning.

Yeah, I expected a mixed response. The "missed tab problem" always crops up and is vastly overblown. C++ of course has the "misplaced semicolon" counterpart to it:

    while (i < 100); //loop body is empty
    {
        // random unnamed block instead of loop body
    }
Oh, and it's kind of difficult to get a bigger screen on a laptop.
> This is the exact opposite of what I want in C++.

This is the exact response I was expecting to go to the top of hacker news -- negative and dismissive. Also, it's nonsense.

Go to a Python mailing list, and count the number of emails complaining that "my program keeps seg faulting unexpectedly" due to "missing a single tab somewhere". Can't find any examples? Well, it would appear that Python coders are more competent than you.

Alternatively, perhaps our eyes and brain are intrinsically wired to easily detect vertical and horizontal lines. Maybe that's why they're so prominent in design -- just a thought. And maybe that's why all C++ programs have some scheme of indentation to denote scope anyway.

I really hate that whenever someone makes a proposal for a language, the zealots, be they lisp or C++ or whatever, immediately come out of the woodwork to heap scorn upon the idea. Personally, I think the kind of change proposed by the OP (with a few modifications) would be really nice, and would give the language a more Pythonic flavour, which isn't called executable pseudocode for nothing.

> If vertical compression is an issue - get a bigger monitor or an IDE that allows for code hiding.

You need to listen to yourself type.

Maybe this is true, but I am just having a real hard time believing a fresh syntax is going to solve any real problems with C++. To do that a language with better semantics is needed, which is a much tougher problem being tackled by D, Rust, etc...
> I really hate that whenever someone makes a proposal for a language, the zealots, be they lisp or C++ or whatever, immediately come out of the woodwork to heap scorn upon the idea.

I often wonder if contrarianism is so prevalent in community discussions simply for the sake of disagreement or to provoke negative emotion. It's completely counter to constructive criticism.

Although to be fair, there are some comments to the contrary that at least make a passing effort to explain what they don't like about the suggestion and why they dislike whitespace languages in general, so I can't tar everyone with the same brush.

That said, considering some of the outright vitriol, I almost feel like someone ought to implement it on principle alone.

> my program keeps seg faulting unexpectedly

Python scripts segfault?

> They're not a "source of errors" -

Yeah I am not entirely agreeing with "source of errors". Usually it is other things like inconsistent syntax or (I am just making it up here) error intolerant syntax. And by that I mean things like:

* I am allowed to use single '=' and '==' in a conditional (in C++). Program still compiles, runs and probably doesn't do what I expect.

* In Python, if I leave an extra , at the end of a variable it creates a tuple ( x = a vs x = a, ). Program still compiles and runs but probably doesn't do what I expect.

* In general think of the time you spent hours and days hunting a bug that ended up being a one character error like above.

In either case, it would be nice if compilers or linters should warn you...

But anyway, I don't think as you were saying, {} are necessary a cause for more or less "errors"

But, { } are a source of visual noise. I think it clutters the screen and it provides an opportunity for strange syntax. When I scan code quickly I don't match up parentheses, I look for nicely formatted and indented blocks of code first. Whitespace and indentation is best for that.

There shouldn't be 100+ page style guides for how to format a language, it should have a one, best, clearest, default formatting and it should be used by everyone. That, I found after programming Python for almost 10 year now, is very helpful.

This looks really error-prone to me.

Have you looked at previous attempts, such as SPECS? http://www.csse.monash.edu.au/~damian/papers/HTML/ModestProp...

Any specific reasons why it's error-prone? I've just seen someone post a link to SPECS in the comments to the post - it's interesting but takes a very different direction. I wanted the code to remain recognisably C++.
Any python developer will tell you they have accidentally indented or un-indented some code, and that error took hours to find
Well I've written quite a bit of CoffeeScript, and while I had a few issues with incorrect code translation to JavaScript, I don't recall ever having problems with mis-indented code.
As another point to triangulate from, Haskell is also whitespace-sensitive and I have never had a non-trivial whitespace error in it.
I've been programming in Python for 4 years and I've never spent hours trying to find an indentation error.

It comes up, sure, but no more frequently than any other syntax error in a different language and there are usually dead giveaways indicating what happened. Most IDEs/editors have options to view whitespace characters, so if you're worried about encountering a bug from this you can always enable that feature.

It's really a non-issue.

This doesn't seem to address http://en.wikipedia.org/wiki/Most_vexing_parse at all.

On the other hand, if you don't care about backward compatibility, I guess completely eliminating constructor syntax in favor of C++11 uniform initialization syntax is a good solution as any. (But maybe curly brace haters won't like that solution.)

I think uniform initialization needs a lot of work before it can become the one and only mechanism for initialization. Currently it isn't anywhere near uniform enough. But aside from that, I think it would be fine to use curly braces for initialization as long as they are freed from the burden of delimiting code blocks.
I'd be fully in support of that if it weren't for the fact that initializer_lists end up causing their own sets of issues.

For instance, type-inference is completely borked:

    auto foo{tmp};
results in

   std::initializer_list<decltype(tmp)>
Not to mention issues such as

    std::vector<int>{ 3, 4 } // => [3, 4]
vs

    std::vector<int>( 3, 4 ) // => [4, 4, 4, 4]
Unless some alternate syntax is proposed for initializer_lists, the old syntactic forms are kind of indispensable.
There's a proposal to fix the 'foo' case but, as an outsider, it's unclear whether it will be fixed in time for C++14. [0]

The vector case is unfortunate, but I'd personally argue the defect is in the vector class. There's no significant performance advantage, that I can see, to the (n, T) construction over a default construction followed by v.resize(n, T).

[0] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n392...

Why can't IDEs just hide all the brackets and replace them with sane whitespace structure?
If your only goal is to read the code, then they could probably do it, after working out a few minor issues. The question is, how do you enter new code? With braces, which vanish as you type, or with whitespace, which means the braces exist only on disk? And if you mess up, how do you cope with the compiler errors?
I love Python and it is one of my primary development languages, but I have come to believe meaningful indentation was a bad idea. As Rob Pike said in the recent Go conference keynote: "It is a profound mistake to have your semantics depend on invisible characters". Braces also make parsing and auto-formatting easier and better. It seems Go struck a good balance with with a newline after statements (no semicolon necessary), and braces for all structures.
Newlines are invisible characters.

Tabs+spaces are the real problem with python indentation. It should be a compiler error to mix them in a file.

While this is now impossible to fix because of backward compatibility, you can use alias python='python -tt' in your environment. Given that option, it is a compiler error(TabError) to mix tabs and spaces.
I would not classify newlines as invisible characters. Except maybe the last newline in the file.

Invisible characters are those that you can't tell if they're present or not. Assuming there are visible characters following, a newline can be clearly "seen" because it shifts the remaining text one line lower.

You must have never encountered a file with mixed line endings.

Somebody should design an esoteric language that uses LF to separate statements in a block and CRLF to separate blocks.

Alternatively, find a unicode line break character that editors recognize, but C doesn't treat as a line break, and sneak it into a source file at a strategic place to introduce a back door.

How about exploring a modern language like Google GO (Golang)? Go was designed exactly for the purpose of having a performance that could be compared to some extent to powerful languages like C/C++ and in the same time maintains a Python like syntax. I have programmed with both languages and I'd say by the end of the day both languages are powerful tools in your developer's toolbox however Go is a very attractive choice when it comes to rapid to develop performant applications
(comment deleted)
This really reminds me of a similar attempt for Go, called iGo [1]. There are a lot more cases to handle for C++.

[1] https://news.ycombinator.com/item?id=7444459

Interesting, thanks for the link. This does look quite similar!
Yep, reading your article I found myself in it and "go" is very simple (compared to c++) however main issue is the readability of function calls with multi lambda arguments.
> I’m quite fond of languages with minimal syntax.

Maybe this is the Lisp enthusiast in me, but as someone who does the bulk of their workaday programming in Python I still feel compelled to say that it's a perverse worldview that holds up Python as an instance of "minimal syntax."

Well, I didn't say that Python is the pinnacle of minimalism :) However, it's hard to reduce C++ to Lisp syntax without completely changing the nature of the language.
Seems like a step in exactly the wrong direction
This doesn't seem to allow single line if or while statements, because parentheses are optional.

I like single line if when it is appropriate. (Python allows single line if by using colons.) Apart from my taste, C preprocessor macros can't expand to more than a single line, so this seems to prevent macros expanding to contain control structures. Is there an easy fix?

You could do it by separating the body with a semicolon:

    if something_is_true(); log("warning!")
I haven't really considered the preprocessor as I prefer to avoid it as much as possible.
This doesn't work. "if a; if b; c; d" is then an ambiguous parse to both "if (a) { if (b) { c; d; } }" and "if (a) { if (b) { c; } d; }". If you decide to parse one way, how do you write the other one in a single line?
I'd make this parse as "if (a) { if (b) { c; d; } }" and leave it at that. One of the reasons for significant indentation is to discourage this kind of code layout because it's hard to read.
Okay, concretely, I'd like to see a translation of this real-world C++ code (taken from V8):

  #define RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \
    if (!__allocation__.IsRetry()) {                                          \
      __object__ = __allocation__.ToObjectChecked();                          \
      if (__object__ == (ISOLATE)->heap()->exception()) { RETURN_EMPTY; }     \
      RETURN_VALUE;                                                           \
    }
This seems to be missing backslashes. I haven't considered how to deal with preprocessor macros, but the if statement converts very simply:

    if !__allocation__.IsRetry()
        __object__ = __allocation__.ToObjectChecked()
        if __object__ == (ISOLATE)->heap()->exception(); RETURN_EMPTY
        RETURN_VALUE
This isn't ambiguous like the example you suggested before.
That doesn't work, because if statement is inside preprocessor macro and must be in a single line.
I see what you mean. Yes, the if in a macro is a problem. I haven't addressed macros, that's a whole different can of worms.
But you can extend lines by putting a \ at the end. I think I was this while looking through some glibc code quite a long time ago. So, you can have a single "line" that happens to have multiple statements.
If it looked more like Python or CoffeeScript, then it wouldn't be C++ anymore.
My goal was to make the code remain recognisably C++, but remove some of the noise.
Nobody needs that

  $ wc -c a.cpp t.cpp 
  399 a.cpp
  380 t.cpp
  779 total
  $ cat t.cpp 
  #include <iostream>
  using namespace std;
  
  namespace utils {
    template<typename T> T square(const T& n) { return n * n; }
  }
  
  int main() {
    int input(0);
    auto message("Please enter a positive number");
  
    cout << message << ":\n";
    cin >> input;
  
    if (input>0) { cout << "Result: " << utils::square(input) << "\n"; }
    else         { cout << message << "\n"; }
  
    return 0;
  }
  $ cat a.cpp 
  #include <iostream>
  using namespace std
  
  namespace utils
      template<typename T>
      auto square(const T& n)
          return n * n
 
  int main()
      auto input = 0
      auto message = "Please enter a positive number"
  
      cout << message << ":" << endl
      cin >> input
  
      if input > 0
          cout << "Result: " << utils::square(10) << endl
      else
          cout << message << endl
      return 0

I am not entirely convinced that t.cpp has any more or less noise than a.cpp and where exactly there is any sort of gain from this – I had more trouble indenting the second piece of code properly for HN than the first.
If you squint in just the right way so as not to see any of the braces, semicolons and parentheses in the first example, then naturally we are going to disagree about the amount of noise :)
Maybe my visual capabilities are just more limited than yours :) That said, I wouldn’t call things like ‘end of statement’ or ‘end of this block’ noise. They have very real effects and using ; and } over "\n" and "\t" seems a decent choice. Natural languages have ".", "," and ";" for a reason, too; although one could argue for paragraphs to be roughly (but only roughly!) block-equivalents and inherently whitespacy.
Since no one has said so yet, and I quickly searched the comments, the answer is basically a language called Nimrod.

It shows up here a lot, and not many people use it still. Time will tell.

If you think that syntax is THE problem that needs to be solved to make C++ less error-prone, you don't know shit about C++.
It has not been mentioned in the original post or the comments yet, so here is a working prototype of a similar idea https://github.com/pfultz2/Pythy (for some specific value of working, you will need Clang)

Its birth lies here Having it all: Pythy syntax for C++ [1]. It was a nice read. Unfortunately cpp-next seems to be down right now. Let me try to find it in Google's cache or internet archive.

Here it is https://web.archive.org/web/20130820172127/http://cpp-next.c...

[1] http://cpp-next.com/archive/2011/11/having-it-all-pythy-synt...

I think generic lambdas provide for this in C++14.
This looks neat on first glance and on small code samples, but I've had so many messed up whitespaces after merging branches that in the real world this would be just another way to shoot yourself in the foot. I really like python for scripting up into the 10k lines-of-code area, but for bigger projects (and teams with more then - say - 3 coders) I wouldn't even consider a dynamically typed language, let alone a language where intendations and newlines are language constructs.

I don't really find the example at the end of the article much more readable (even though it "cheats" a bit by using the C++11 auto keyword and range-based for loop), on the contrary, the white space on the left side looks more messy then on the right side to me.

C++ code which has a lot of STL containers and complex templates does look ugly though, that's why I prefer to either not use this, or hide it under typedefs and decltypes. I also don't like the new auto keyword very much, the compiler SHOULD complain when someone on the team changes types around.

What if I wanted to take a peek at this article without giving up my email address? If only there was an easy way to stop JavaScript from blocking my page view with that subscribe request …
Python is easier to type but its harder to read. Ides that help you code faster are a better investment of time than a language that's easier to write in notepad. My ide does brackets and indention for me. I never think about them. They're just there for my reading pleasure. I like these things its easier to follow the code when reading.
I would support this if you can remove header files. It is hell to manage function prototypes. Let the compiler figure that out with "public/private" keywords.