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.
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.
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.
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.
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.
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.
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++.
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.
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.
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.
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).
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.
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
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.
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?
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.
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.
$ 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.
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.
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.
78 comments
[ 2.4 ms ] story [ 87.9 ms ] threadA 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.
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.
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 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:
With whitespace sensitivity, this would do what you think it would. With curly braces, it's misleading.TBH, the real problem with C is not the braces - its that braces are optional.
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.
Back in the 1970s, I chose tabs to save bytes in my text files. Today I feel like I can afford the extravagance.
Clearly we both can't be pleased. ;)
[1] Except in Lisp.
- 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.
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.
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.
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.
Python scripts segfault?
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.
Have you looked at previous attempts, such as SPECS? http://www.csse.monash.edu.au/~damian/papers/HTML/ModestProp...
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.
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.)
For instance, type-inference is completely borked:
results in Not to mention issues such as vs Unless some alternate syntax is proposed for initializer_lists, the old syntactic forms are kind of indispensable.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...
https://github.com/lukesdm/little-braces
Tabs+spaces are the real problem with python indentation. It should be a compiler error to mix them in a 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.
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.
http://en.wikipedia.org/wiki/Whitespace_(programming_languag...
[1] https://news.ycombinator.com/item?id=7444459
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."
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?
It shows up here a lot, and not many people use it still. Time will tell.
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 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.