9 ms·
I have been programming in C for the last 25 years, and every year or so someone comes with a new shinny thing that will "replace" C. First it was C++ (we know
by coliveira 6y ago
I have been programming in C for the last 25 years, and every year or so someone comes with a new shinny thing that will "replace" C. First it was C++ (we know how well it did...), then Objective-C, then Java, then C#, then Go, and now rust.
Everyone of these language brought new ideas, but they don't stand a chance because their designers don't understand the point of C. The C language didn't win because it was the "best" language or had the best set of features. Far from it. Even in the mid 70s it was a backward language compared to other cool languages of the day like Algol and Lisp.
C won the competition because it just gives programmers the bare minimum functionality to put an operating system and a compiler in place! It is flexible, you can provide your own library if you want, and therefore gives your easy portability. OS writers will chose C any hour of the day or night because it makes their job easier.
By comparison, other languages will require a huge library to be available, and sometimes a complex runtime system, just for you to write a simple "hello world"! Imagine if you need to write a new OS, a compiler, a linker, or a shell interpreter... you get the idea.
My conclusion is that language designers still didn't get what made C so successful and therefore keep coming up with shiny complex things that don't stand a chance to become the next C.
- coldpie 6y agoI'm in a similar position (only 10 years professionally though). I agree with everything you said, except I think Rust genuinely has a shot here. It doesn't have a runtime, and you can choose to use just the core libraries or even no standard libraries. It exports to the C ABI, so it's compatible with existing software and libraries. It isn't a garbage pile like C++. And it solves a real problem C has, code safety. It's silly to say any language will completely replace any other language, but I think Rust fits into the slot pretty well for the vast majority of cases where C is currently the best choice.
- coliveira 6y ago> I think Rust genuinely has a shot here. People proposing every other language that tried to replace C thought the same. Only time will tell, of course, but I wouldn't bet on it. Nowadays C++ is seen by many as a "garbage pile", the same can happen to rust.
- masklinn 6y ago> Nowadays C++ is seen by many as a "garbage pile", the same can happen to rust. C++ was seen as a garbage pile from its inception by a large number of people. A significant number of people kept using C because the only alternative was C++ and that wasn't acceptable.
- johannes1234321 6y agoThee is an important difference between C++ and Rust: C++ tried to play the game by being a superset of C (even started as a precompiler to C) and many C programs are valid C++ (well, many C programs aren't valid C, let's ignore that here) Thus C++ always carries C's legacy along so that there is always the C way of doing things, and then the C++ way of doing things. Rust cut that part of, while allowing to call C functions.
- einpoklum 6y agoAlso, Rust has taken the path of backwards-incompatible changes, while the C++ language designers/committee go to great lengths to maintain near-perfect backwards compatibility with older versions of the language (and refuse to allow for ABI-breaking changes! Grr!)
- MaxBarraclough 6y ago> and refuse to allow for ABI-breaking changes! Did you mean API? The C++ ABI situation is famously unstable.
- einpoklum 6y agoNo, I did mean the ABI. See this paper, for example, about the argument: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1863r1.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p186... "there is a non-trivial amount of performance that we cannot recoup because of ABI concerns. We cannot remove runtime overhead involved in passing unique_ptr by value, nor can we change std::hash or class layout for unordered_map , without forcing a recompile everywhere etc. etc."
- optymizer 6y agoI tried to learn Rust 4 times. I'm sorry, but I can't get past the syntax. Just _look_ at all these short keywords and special symbols. It's legitimately hard to read without focusing on each character. #[bla(foo)] fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) { println!("x is {} and y is {}", x, y); } impl<'a> Default for Borrowed<'a> { fn default() -> Self { Self { x: &10, } } } This old fart thinks Rust is the new Perl.
- coldpie 6y agoWell, that is a particularly complicated example. I actually shipped my first Rust code just a couple months ago and it rarely used lifetimes. There is definitely a learning curve, but that true of any language. Rust's insistence on safety makes it less forgiving than other languages, but I think that's a plus. We have enough unsafe languages already, and we're paying the price for it now. Here's a representative example of the code I wrote. This bit is outputting stuff to a file in some binary format: https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/fossilize.rs#L211 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... E: If you want to take another stab, the way I learned Rust was the book: https://doc.rust-lang.org/book/ https://doc.rust-lang.org/book/ Actually type out every code example, it will help your fingers learn the "feel" of the language, and give you an opportunity to break things on purpose to test your understanding. Learning something new is always a challenge, but I really do like Rust and think it's worth the trouble.
- optymizer 6y agoThanks for providing a real world example of code that looks fine in Rust. If you're not using lifetimes, do you still get all the safety guarantees?
- coldpie 6y agoYes, definitely. You only need explicit lifetimes for when it's impossible for the borrow checker to figure out the lifetimes for itself. For example if one struct references another, the borrow checker can't know which struct should outlive the other. The vast majority of the time, the borrow checker can figure it out automatically without your help. It's discussed here[1] but note that it's Chapter 10 of the book, so it's probably not the best place to start reading if you're new to Rust :) [1] https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html E: There are only three instances of using explicit lifetimes in the entirety of the project I linked, if you want to see some real-world examples of it. In all of these, it is used to indicate that the struct being declared references another struct which must outlive that struct. That way we don't end up with a dangling reference if the referenced struct failed to outlive this struct. https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/audioconv.rs#L406 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/videoconv.rs#L133 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/videoconv.rs#L433 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med...
- bluecalm 6y agoRust has a terrible, verbose syntax and solves a problem that is a non issue in many applications where C shines while making ordinary things difficult (like recursive data structures). I am sure it has its place but I think it's just too ugly to be attractive. There is something pleasing about writing C, Python or even Javascript which you will never get with Rust. It will never be a language a lot of people enjoy writing imo.
- arcticbull 6y agoUgly is a matter of opinion of course, but once you start to write it you get a sense of what "looks good" and what "looks bad" and you start to write nice looking Rust if you want to. I can show you some powerful ugly C haha.
- bluetomcat 6y agoI see C as a minimally-viable HLL. Just the essential high level stuff – expression-oriented syntax (a huge thing over assembly), structured programming support (conditionals, loops), automatic storage management (no worries about what goes in registers and what goes at certain offsets in the stack frame), abstraction over calling conventions, and a rudimentary type system around scalars with a certain size and pointers pointing at them.
- coliveira 6y agoThat's my view too. The surprising thing is that a minimally viable language is still able to accomplish so many things.
- jcranmer 6y ago> C won the competition because it just gives programmers the bare minimum functionality to put an operating system and a compiler in place! Not really. C won because it was the standard compiler for Unix, and was a free compiler for a free operating system in a time when both were highly unusual. But in the past few decades, C has lost a lot of its market share to other programming languages. In the realm of desktop (and mobile) applications, C is basically unused for new projects--its standard library is truly anemic here, and major support libraries (e.g., GUI toolkits) are often in C++ and not C. Where C is still the dominant language is the land of embedded applications, and it's not had a lot of competition here since most languages don't bother trying to define a freestanding implementation. Rust is really the first language to try to contend this space. And there are signs that it may supplant C: Intel is apparently looking to move its firmware to Rust; Linux is allowing Rust for device drivers and kernel modules. Hell, even some OS programming courses (e.g., Stanford, Georgia Tech) have moved their curriculum to use Rust instead of C.
- coldpie 6y ago> Linux is allowing Rust for device drivers and kernel modules. Oh, did this happen? I remember some discussion some months ago, has it actually been merged?
- jcranmer 6y agoNothing has merged yet, but the basic plan to start allowing Rust has been approved at a high level.
- witherk 6y agoI'm enrolled for a masters at Georiga Tech right now and last I checked the OS course is in C, I would kinda prefer to learn rust anyway so I hope you are right.
- steveklabnik 6y agohttps://tc.gts3.org/cs3210/2020/spring/info.html https://tc.gts3.org/cs3210/2020/spring/info.html Dunno how often this class runs, and if it was just for one semester or more than that.
- qppo 6y agoLanguage designers are pretty clever people and understand a great deal about the successes and failures of languages. I think if you look at a lot of what Rust is doing today (and C++ yesterday, for better or worse) you'll see a lot of inspiration and influence from the successes and failures of C. Particularly when it comes to safety and generic programming. Objective-C, Java, Swift, and C# have become massively successful as application programming languages because C is/was terrible at it. They learned a lot about how painful it was to do basic higher level programming tasks when you are restricted to C's semantics and memory model. C is great but I don't think it's worth romanticizing since history has shown that C isn't that great for writing anything but systems code. Which is a restricted domain to begin with, and isn't even that attractive for it anymore. The one thing C has over anything else is interop. The language of FFI is C. There's no inherent reason for that other than history, and it's not super broken so we're not going to fix it.
- bluecalm 6y agoGames (many in C++ with one or two features beyond basic C). All kind of solvers. GPU programming. C sucks when you need convenience of big standard library or safety above performance. There is nothing like C when you care about speed, memory footprint and efficient memory management. It's great other languages took over in areas C is terrible at but it's not like areas when it's the best and often they only option disappeared.
- qppo 6y agoThese specific claims are flaky at best but hard to argue over since anyone can construct enough cases for or against their position to be right enough not to change their opinion of C. You can absolutely beat C in everything you list. And you also can't. I don't agree that C is the end all be all of performance or code size, except in a handful of cases where there's nothing else available.
- kazinator 6y agoC won over because of the mystique of the syntax in which you can load multiple side effects into expressions. The intuition was that this leads to faster code, and in fact, with naive compilers, it did lead to faster code. C's terseness won over programmers who hated typing things like BEGIN and END for delimiting blocks. Unlike Pascal or Modula, C came with something very useful: a macro preprocessor. This is such an advantage, that it's better to have a crappy one than none at all. Those programmers who did not hate BEGIN and END could have them, thanks to that preprocessor. The preprocessor also ticked off a checkbox for those programmers who were used to doing systems programming using a macro assembler. C started to be popular in the microcomputer world at a time when systems programming was being done in assembly languages. For instance, most arcade games for 8 bit microcomputers, were written in assembler. Some applications for the IBM PC were written in assembler, such as WordPerfect. The freedom with pointers thanks to arithmetic would instantly make sense and appeal to assembly people, who would find a systems language without pointer flexibility to be too strait-jacketed.
- 0xffff2 6y agoI would argue that Java and C# completely succeeded. Who is out there writing Desktop applications or web services in pure C anymore? C++ too to a lesser extent. I work on spacecraft flight software, and there's a significant push to move from pure C to modern C++. No single language is going to (or wants to IMO) replace C in every single use case, but replacing C in specific use cases has been a huge boon for productivity.
- cogman10 6y agoRust, I'd argue, is the language trying to really take on most of the C use cases. The only one it's really not trying to take over is old embedded work where C is pretty much the only option. Otherwise, I can't think of any circumstance Rust isn't trying to muscle in on C and C++'s territory.
- einpoklum 6y agoI like C fine, and I also taught it when I was in grad school. New languages mostly don't replace existing ones. Rather, they supplant them for some uses, and open up new kinds of software which are easier to implement or to conceive with the new language. Now, you referred to C++ specifically, and since I'm somewhat familiar with it I'll address some of the points you made with respect to just that one: C++ was not intended to "replace C", but rather to combine features of BCPL (later C) and Simula. See: https://www.youtube.com/watch?v=69edOm889V4 https://www.youtube.com/watch?v=69edOm889V4 Bjarne Strousup said: "If you want to create a new language, a new system - it's quite useful not to try to invent every wheel." For a long while now, C++ teachers/trainers encourage their audience _not_ to think of C++ as an "augmented C" or "C with feature X Y and Z", and to avoid most "C-style" code in favor of idioms appropriate to what the language offers today. Also, C didn't "win the competition" because there isn't a "bestest language for everything" competition. It has been, and is, a popular language with many uses. Writing operating system kernels is one kind of programming task, where C is the most popular. Even at this level (and lower still), other languages are potentially interesting and often used. See, for example: * IncludeOS - Running C++ without an operating system: https://www.youtube.com/watch?v=cQPrtTsM7Zg https://www.youtube.com/watch?v=cQPrtTsM7Zg * Generating optimal assembly in an embedded setting at (C++) compile time: https://www.youtube.com/watch?v=CNw6Cz8Cb68 https://www.youtube.com/watch?v=CNw6Cz8Cb68 Finally, C++ doesn't require a huge library nor a complex runtime system because it has a "freestanding mode" in which the requirements are very limited (although more is required than for C). See: https://en.cppreference.com/w/cpp/freestanding https://en.cppreference.com/w/cpp/freestanding
- loup-vaillant 6y agoYou probably don't realise it, but you're cheating. Operating systems are currently written in C, and therefore have a C interface. Which language is best at interfacing with C? (No trick here, just a rhetorical question.) C of course. Other languages would need some sort of FFI, which is generally unwieldy enough that the designers hid it behind a comprehensive standard library. C doesn't need an huge library to be available, you say? Oh but it does. It's called the kernel. Comes with a freaking huge runtime too. > Imagine if you need to write a new OS, a compiler, a linker, or a shell interpreter... you get the idea. I think I do, but I'm afraid you don't. Writing an OS (and the rest) in Pascal (I'm thinking of Oberon specifically) is no harder than to write it in C. If you write your whole OS in Blub, interfacing with Blub will be easiest in Blub, you won't need an extensive Blub standard library because you already have the kernel, all the tools (debuggers, editors…) will be Blub friendly… Lisp machines used to be a thing, you know. > My conclusion is that language designers still didn't get what made C so successful […] Language designers can't even address what makes C so successful: network effects.
- josephcsible 6y ago> Operating systems are currently written in C, and therefore have a C interface. Not true. Operating systems are written in C with some assembly, and the interface to userspace is universally written in assembly. E.g., https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/entry/entry_64.S?h=v5.9.8#n95 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux...
- loup-vaillant 6y ago> the interface to userspace is universally written in assembly. Which by some eery coincidence happens to conform to the C ABI of the platform. Come on.
- josephcsible 6y agoThe point is that it has a C interface despite being written in assembly. Your original post said the only reason it had a C interface was that it was written in C.
- jcelerier 6y ago> First it was C++ (we know how well it did...) it did well enough that C stdlibs (at least MSVC's, LLVM's) and compilers (... pretty much all the big ones) are implemented in C++ and just export C symbols nowadays, likewise for newer OSes like Fuschia. SerenityOS (https://github.com/SerenityOS/serenity https://github.com/SerenityOS/serenity) was written from scratch in two years in C++ and goes as far as having a custom web browser & JS engine. Where is the equivalent in C ? Where are the C web browsers, C office suites, C Godot/Unity/Unreal-like game engines ? Why is Arduino being programmed in C++ and not C ?
- young_unixer 6y agoThank god for C winning that battle. Imagine a world where most the languages follow Lisp's syntactic conventions, or Pascal's. What a nightmare.
- Banana699 6y agoAs opposed to C's syntactic conventions, the absolutely gorgeous mush of *s, &s, __MACRO_LIKE_FUNCTIONS___() and #preprocessor directives The default is not the best, the default has just beaten the world so many times on the head that anything else became foreign and weird and got laughed out of the room before it even had the chance to say anything. One programming language history book/blog/paper a day keeps the nonsense notions away, C "Won" like people win the lottery or the roulette.
- int_19h 6y agoWhen it comes to declarations, the world is already moving over to Pascal's syntactic conventions in some ways. In newer languages, you see something like this: var x: *int; more often than: int* x; i.e. type name follows variable name, and type modifiers work more like unary prefix operators on types. And this is because it's less ambiguous to parse, and makes more complex types a lot easier to read, since you simply go left-to-right, instead of C's "spiraling" declarations. The rest of Pascal's syntax is not particularly problematic, either. I'd say that the two biggest problems with it were begin..end for blocks, and having all local declarations in a block separate from code. But Modula-2 already dropped "begin", and various Pascal dialects added inline variable declarations eventually. So, on the whole, I think we'd actually be better off in terms of code readability if Modula-2 rather than C became the standard systems programming language.
- Gibbon1 6y agoThing that makes me somewhat sad is there isn't much reason why you couldn't fix some of C's syntax and other issues. I feel like any breaking changes wouldn't be that big of deal as long as you have a backwards compatible ABI. Say you add fn and var as keywords. Exactly how hard would that be to fix? You could probably write a tool to do that.
- WalterBright 6y agoIf you use D as Better C, it does not require anything other than the existence of the C standard library. Here's "hello world" in DasBetterC: import core.stdc.stdio; int main() { printf("hello world!\n"); return 0; } and yes, it is calling C's printf. To build it: dmd -betterC hello.d