This is from my favourite book: In the beginning was the command line.
[0] https://web.stanford.edu/class/cs81n/command.txt , search "HOLE HAWG".
This “sometimes you need a knife" argument just doesn’t make sense. You can have the power and the safety. Stop cutting off your fingers.
> This “sometimes you need a knife" argument just doesn’t make sense. You can have the power and the safety. Stop cutting off your fingers.
Sometimes you need a scalpel.
I'm not against Rust. I still want to start a project where Rust will be worth learning for me, but I'm currently busy writing erlang and java for big systems and C for microcontrollers. This is of course only my local situation, I don't advocate for those languages (I love erlang though and I'm wishing for advertised easy concurrency in Rust, maybe someday).
I don’t think Rust should be used everywhere, but I’m firm that it could be used anywhere that C can (short of an unsupported architecture).
I think Rust’s reputation for being hard to learn is overblown. Yes it is probably a little more esoteric than what you’re familiar with but any decent dev should be able to pick it up
They were far less homogenous in the early years. Today you have a octet addressed little endian integer machine, with ieee float hardware and a small vector unit. Maybe you have two different instances of that on the same address space, but probably just one.
I think reasonable argument could be made that the complexity in modern computing is primarily self inflicted by software engineers.
But, people aren't writing K&R C. These days most of them are writing something closer to C99 or C11 and some may be using something newer (e.g. C17) or proprietary (GNU's C dialect) either deliberately or just because it compiled and nobody told them not to.
At that point you've actually given away much of the simplicity, and yet what you get for your trouble is largely more footguns. Trade up for a sound type system and fewer footguns instead.
Next one is what, the C11 memory model? Doesn't take away any simplicity, just defines things better.
C11 atomics would have been much better if they'd standardised existing practice instead of inventing something based around the application centric design C++ was inventing. It's nice that there's an acquire/release scheme one can reason with but a real shame that they conflated it with type annotations.
In both those cases the K&R C model was very simple. You could decide you love how simple this model is, and when smarter compilers optimise it into a pretzel or other languages are faster that's OK. This code used to drive the serial port, now it does nothing, OK, don't use C to write such drivers. This code used to go real fast, now everybody else is faster, OK, don't use C if you need the best performance.
C89 and C99 choose different, making the language more complicated to keep addressing performance and compatibility. In C99 I can write the fast serial port driver, but it's significantly more complicated as a result. The beginner will definitely get it wrong and explaining why is pretty subtle.
Then C11 says actually you're not writing sequential programs, which was a crucial simplification in K&R C - the programs you can write do one thing at a time, in order, and then maybe stop. The memory model in C11 is needed because it says actually your programs might do more or different things at once.
Now, in reality by 2011 lots of people were writing C that's not actually sequential - after all SMP Linux long pre-dates C11. But those weren't legal C programs, they're GNU's dialect and so all bets are off. Nobody is claiming Linux is simple.
So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
If you don't want to do SMP / lock-free programming, you don't have to pay for the complexity. You can still write "sequential programs" like it's K&R. Don't do multiple threads, and you don't have to care. You can also do multiple threads but use mutexes for synchronisation, everything will be fine.
Pretty much nobody uses restrict or volatile. There is some fringe stuff that is obsolete and maybe badly designed, but by and large you don't have to use it or interact with it. Compare this to other languages / ecosystems which have this amount of cruft times 100.
It's still this language where you can define a struct, then define a function that receives a pointer to the struct, and it does as you say, and you can actually read and understand the code a month later.
If you need to go fancy for a reason or another (most likely a bad reason), you can do that too, and of course you'll have to pay for it. But most likely, the complexity is not "cancerous" -- define a simple function interface with the most basic assumptions you require, and the complexity is pretty much isolated behind a simple pointer to an opaque structure.
> So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
That's ridiculous and you know it.
"Faster but wrong" isn't really faster it's just wrong.
> That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
What other threads? In a sequential programming language we certainly can't have "other threads".
> You can still write "sequential programs" like it's K&R.
"You can just not use the bits you don't like" is how we got C++ dialects that C++ proponents love to pretend don't exist. If the language is "simple" except for all the new bits that are complicated it's not simple.
This makes simple application code slightly faster. That's kind of a reasonable domain for C++ but on dubious ground for C. Where C is superb is talking to hardware and language implementation, exactly the areas the ISO group has chosen to cripple the language for.
Thankfully compilers know about this and provide fno-strict-aliasing et al. Maybe there should be a std= style flag to change to the language subset that doesn't actively try to miscompile your program chasing benchmark numbers.
However, if you reduce the language surface it is possible to have something safe and simple enough (IMHO).
For instance, you can say no async, no custom traits and only {Debug, Display, Eq, PartialEq, ...} are allowed for your structs and generics. From limited personal experience that takes away more than half of the complexity of navigating rust code.
You might be able to outsource some complexity to external libraries, but integrating libraries is itself a major headache, and it can lead to security issues too.
However, I believe the being "opt-in" by explicitly marking sections unsafe is the way to go instead of having unsafe by default (which is the only way using C).
You don’t need to outsource complexity anywhere. Rust is fully capable.
I might try it out if these two requirements were met. I have a mental model between what I write in C and what I can expect the assembly to be.
Or maybe the problem is that we have the same stack for code and data? could that be it?.
Totally agree with you: use the best tool for the job.