As I get older and grumpier I tend to appreciate Linus' point of view more and more. It's easy to get swept up by arguments of the expressiveness of a language, particularly in small examples. However, I think in the long run it's better to have very explicit code. The less jumping around and inference I have to do to figure out what a block of code does the more likely it is that I understand it and that I can quickly verify that it does what it needs to do. If that makes code a little more verbose I think it's usually still worth it.
> <i>One of the absolute worst features of C++ is how it makes a lot of things so context-dependent - which just means that when you look at the code, a local view simply seldom gives enough context to know what is going on.</i><p>Good point. Very good point.<p>Having spent few years developing for the Linux kernel I can say that the most cluttered code I dealt with was the network stack. And exactly because it was done in C++-ish way. It makes an extensive use of tables of function pointers, which is basically an analog of a C++ virtual table. A socket depending on its type would get a pointer to a different table and that table would define the actual flow, say, of the recv() call in the kernel. The concept is very elegant, and it translates into a more compact code, but it also makes tracing the code by hand hard.<p>So, yeah, Linus got a point there :)
I think Linus is making the right call here. At a 10,000 foot view, the real argument is about style. The style of C happens to be one that lends itself to easier groking of code amongst hundreds of developers (as he illustrated well). Sure, C++ may be a more modern tool with some more powerful features, but using it may not be the best thing organizationally.<p>This kind of thinking is refreshing and is seemingly rare in classrooms. There, you mostly learn 'what to use' and not 'how to determine what you need'. Just as I'd expect, over design is the most consistent issue I come across in co-workers' code. 'Write code to be read' is a metric that seems to have gone out of style. Code that does X-Z-Y should, in my opinion, look like code that does X-Y-Z. Otherwise the reader has to invest time and energy figuring out the design. There had better be a good reason to justify a hard-to-grok design, because it will continue to be a drain for the life of the project.
Linus has a touch of what I think makes Steve Jobs great: the ability to say no and stick by those convictions. No argument from me that Linux is wildly successful and one of the most important tech developments in the last 10 years.<p>However, I always cringe when I read some of his comments that seem to reject any element of forward progress. While C++ certainly has its share of issues, Linux will never evolve if the programming paradigm stays in the 60s. My gut feel is there is a lot of opportunity to do better over the next ten years.
Let's put it this way without any subjectivity: every production kernel that you folks use every day is written in C. NT is, Solaris is, Darwin is, and Linux is.<p>Not <i>one</i> production-level kernel that is in wide use as a general-purpose operating system uses C++. I don't believe that to be a coincidence.<p>(Nitpicker's corner: Darwin's device tree subsystem is written in Embedded C++, an extremely cut-down version of C++ that's more like "C with classes" than C++).
I actually liked his point about context very much. In fast moving projects changes are visualised in terms of diffs, and the closer the code is to what will be executed, the more chances that obvious flaws will be caught. btw related discussion in an older thread - <a href="http://news.ycombinator.com/item?id=1318489" rel="nofollow">http://news.ycombinator.com/item?id=1318489</a>
It is funny how a very simple and innocent looking question by "newbie" started a big discussion. It is like watching somebody drop a candle in a bed.<p><pre><code> Can you use C++ in Linux kernel?
In windows kernel you can, with some restrictions.</code></pre>
There's not much "Linus vs C++" in there (except for several random bashes with nothing to back them up). It's mostly Linus sharing his POV as the maintainer of the kernel as to why C++ would be harder to work with in a project that has many contributors due to code being more context dependent (i.e member functions, function overloading).
There are so many large scale C++ projects that prove Linus wrong every day. One of them, you probably use it every day. hint: it's a search engine.<p>Whatever language you use, you need rigor and diligence. You need to manage the project and follow up on developers.<p>You need to agree on a subset of the language, that will become your local dialect. I'm pretty sure that Linus doesn't accept "any C source code".<p>C++ has got more features than C. That's neither intrinsically good or bad.<p>I could argue about the merits of templates and what they enable you to do, and someone would tell me "it's hard to understand".<p>Well, any language you don't know is "hard to understand". C++ is not "C with classes" anymore. It's something else. It's a different language.<p>In the end what <i>really</i> matters is the quality of the developers and the quality of your process. The language is just how you implement your concepts.
This leaves me with a burning curiosity.<p>Linus, if you could change the Linux kernel to another language, would you?<p>In a perfect world (i.e. migration concerns and such aside), if you were changing the Linux kernel to another language, what language would you choose? If you feel C is still the #1 choice, what would the #2 choice be?
Wow, Linus is getting older : he didn't flame the poor guy down.<p>I feel a bit concern that Linus don't write code anymore but still decide on how code is written, etc... Happily, he has some experience.<p>Linus has good reasons, nobody is going to rewrite linux in C++ anyway, this has been debated to death.<p>Why I am still loosing my time commenting on this ?
It's right, that in theory I can't know what a C++ function call means.<p>But that's also the case for C. In C I can assign a function pointer to a variable. When the function is called through the variable, than I don't know which function is called.<p>Almost never the language is the problem, but their usage.
There's always context, and the quantity depends mostly on the complexity of the software. And regardless which language you use, you have to define a convention for the usage of the language, also in C.
I've seen some pretty clean C++ code and some ugly C code. I think what's important is how a programmer use a language rather than what language he uses. I mean, if someone enjoy writing clever one liners, he/she will probably do it in all languages, might it be Perl or C. However, the important point here is that C does a good job and the programmers are used to it and like it. THEY, people that submit patches, like it, period.
Even if the Linux kernel were rewritten in Erlang and it won't change the fact the vast majority of *NIX systems level code is entrenched in C. The most popular LAMP stack ingredients are also written in C. Face it; it's a good language.
Regarding C and C++ I sometimes think of them like this:<p>If you want a language that's like C but better, tough, just use C.<p>If you want a language that is better than C, do <i>not</i> use C++.
It makes a lot of sense if you think about it as optimising code readability for the case of seeing it through the lens of<p><pre><code> diff -pu -c 3
</code></pre>
which is basically what Linus does all day. This also implies that the argument has little meaning in the context of projects that aren't comparable in scale (both code size and contributor pool size).
Could Linux explain spinlock.h then? Depending on which <i>type</i> you give to the PICK_OP macro, it performs a different operation. Its basically a C template. Seems a bit weird to complain about type context specific code and then use it in one of the most important parts of the kernel..<p>Here's the code:
#define TYPE_EQUAL(lock, type) \
__builtin_types_compatible_p(typeof(lock), type <i>)<p>#define PICK_OP(op, lock) \
do { \
if (TYPE_EQUAL((lock), raw_spinlock_t)) \
__spin##op((raw_spinlock_t </i>)(lock)); \
else if (TYPE_EQUAL(lock, spinlock_t)) \
_spin##op((spinlock_t *)(lock)); \
else __bad_spinlock_type(); \
} while (0)
"And the best way to avoid communication is to have some
"culture" - which is just another way to say "collection of
rules that don't even need to be written down/spoken, since
people are aware of it". Sure, we obviously have a lot of
documentation about how things are supposed to be done,
but exactly as with any regular human culture, documentation
is kind of secondary."<p>This is so true - I have zero problems with context sensitivity and difficulty reading C++ if its all consistently done according to my prefered standards (which I mostly inherited from an especially well managed employer), avoiding the "bad practices" that introduce these problems like namespaces and such. Yet if I dive into some poorly organised and written code I can easily spend a whole day debugging a trivial problem - simply because the time is wasted trying to understand what is happening.<p>The sad truth is that the latter case is more common - its not C++'s fault though (although it could just /not/ try and provide every imaginable feature) - its more bad management than anything else. Though I can't help but wonder if that is just unavoidable for inherently difficult to manage projects like this...
Many of the arguments he gave are mostly just based on the fact that there aren't that much powerful tools around which can do what he requests (and what of course is something you want to have).<p>Like grepping for all usages of some function. Or getting some code snippet in a way that it comes with all necessary context. Or whatever.<p>Though, with recent development (particularly on clang), these things may become much more easier. Of course, you will not be able to do magic things (like checking at what places what particular virtual function implementation is called exactly) but it will be trivial to check for example all calls on std::string::size etc.<p>In the same way, you could also implement some small helper tool for sharing code snippets which will add some meta information about the context. So that when you share some code like 'a += "foo";' it will contain the meta information that a is an std::string.<p>LLVM/clang is anyway also kind of a disprove to his arguments about maintainability. I would say that one reason that working on/with the LLVM/clang code is so much nicer compared to working on/with the GCC code is because it is written in C++.
I know no tool would solve every problem, but I can't help but wondering if someone developed and IDE that truly got C++ would that allow C++ to be used by more projects. Seeing grep referenced for code searches reminds me that grep has no knowledge of the context of anything in a searched file. It almost seems like C is the only choice if you can't go beyond context-less tools.<p>//a grep specifically for C++ code - hum
C as a context free language? Bullshit. How many global variables are there? How many functions with ridiculous names like htons?<p>Edit:<p>I realize that "context free language" was a poor choice of words; i meant it in the sense that linus did - his claim that you can 'look at a piece of code and understand what it does' is laughable in the face of accepted c programming styles.
I'm immediately skeptical of people who think modularity, inheretance, and polymorphism are a bad thing. Linus never comes out and says as much, but by indicating that he doesn't want to jump around to learn how a bit of code works he's implying it by desiring as few dependencies within code as possible.<p>I certainly apprecate Linus' genius and the revolution he brought to computing, but we live in a different world than when he first took up C programming. Computers are far more capable than they were decades ago and we've taken advantage of that by making code much more flexible than in years past. The result is far more code reuse than early OO programmers ever thought possible.<p>Could this possibly be the worlds first programmer-generation gap?
<i>That is a huge problem for communication. It immediately
makes it much harder to describe things, because you have
to give a much bigger context. It's one big reason why I
detest things like overloading - not only can you not grep
for things, but it makes it much harder to see what a
snippet of code really does.</i><p>I think this is a limitation of our using flat text to program in. So long as our primary means of communication is linear speech and flat text, we will have this communications overhead. Collaborative systems that display the context to all concerned can overcome this. In fact, this is already happening! (Exercise for reader.)
Somewhere down the list, someone asks about Go<p><i>Hey, I think Go picked a few good and important things to
look at, but I think they called it "experimental" for a
reason. I think it looks like they made a lot of reasonable
choices.<p>But introducing a new language? It's hard. Give it a couple
of decades, and see where it is then.<p>Linus</i><p>(<a href="http://www.realworldtech.com/forums/index.cfm?action=detail&id=110624&threadid=110549&roomid=2" rel="nofollow">http://www.realworldtech.com/forums/index.cfm?action=detail&...</a>)
Because the Linux kernel is so important, and so difficult to replace, people will put up with whatever language inconveniences they must in order to get their contribution accepted.<p>Therefore, I don't see Linus' choice as having any larger significance.<p>I already know that C++ is a vastly superior language to C for small to medium scale programs where computational time+space efficiency is paramount.
He falls in the same mistake of many people: thinking that because there's operator overloading in the language, you have to use it. The same for templates.<p>Most successful C++ projects never use some features. Some even use C macros instead of templates, like wxWidgets. It both works and compiles fast.
This rings hollow. It's like saying "C++ feature X can go horribly wrong when used without adult supervision, therefore C++ is unusable." This is especially silly coming from someone who favors a professional stunt language like C.<p>If somebody uses too much overloading, reject their patch. If somebody makes a template tarpit, abuses operator(), or gets too fancy with operator overloading, send it back to 'em.<p>Context dependency bad? I <i>like</i> having the superclass define a contract so that you can ignore which subclass is being used. And C++ even rubs your nose in the name of the superclass, to avoid duck typing (which Python/Ruby use with near impunity anyway).<p>Polymorphism also gives you what amounts to functional programming without touching C's awful function pointer syntax. I suspect a lot of Linux code uses baroque switch/case or "if" statements just to avoid the pain of function pointers.<p>Edited.