20 years from now, C will probably still be a core language in its niche.
20 years from now, C will probably still be a core language in its niche.
Dr. Hipp spent years achieving this, and any reimplementation will suffer his travails, regardless of language safety.
DO-178B means that SQLite can be used in avionics. No other major database has reached this level of code quality, as the database written for "programmers who are not yet born."
All versions of SQLite released after that time are run through the test harness that maintains this standard.
Looks like it may not be used exactly in avionics (or maybe most critical parts of avionics), as it isn't certified for the highest levels of DO-178B (and certification for lower levels was done by particular users of SQLite on their own, so the info is not public). Still very impressive.
They would not have done so if they had no plans or intention to deploy it.
I would be surprised if they were not able to do so.
[1] There have been multiple articles on HN where a single person has written a C compiler.
it's probably always better to do it with someone else, because you get better ideas and faster debugging, but pretty much all hlls are possible for a single person to implement
I think C and its direct descendants will slowly fade away over the next 20 years as new developers want to get away from the legacy of language specifications that span existing codebases. There are so many sharp edges in C that have automatic fixes/detections/etc in newer languages and don’t get me started about multiprocessing complexity in C.
He knows Rust well but software design not so much. I know software design well but Rust not so much. My experience can be summed up with:
let &mut writer = Writer<T>::writer::new(connection.clone()).clone(); // TODO ??? writer.write(*data.clone()).unwrap();
Meanwhile in C++ I'm like
if (!write(connection, data, data_len)) { return false; }
let &mut -- Essential keywords.
writer = -- Duh
Writer<T> -- Generic types. Important.
::writer::new -- Boilerplate.
(connection.clone()).clone; -- Relentless cloning is a big problem.
...
.unwrap -- "Consistent names for optional types," is an issue in Rust. Every module has different jargon for Some(x).
Rust certainly isn't perfect. The borrow checker creates... awkwardness, that requires .clone hacks to solve.Flip-side is, I'm coding in CMake right now. I've had to create multiple bash scripts for manually deleting my build files and general day to day.
Software is a young profession.
Everything is shit.
clone() itself makes perfect sense. Why the programmer needed those clones... is a legitimate issue with Rust.
In my experience so far, it's usually to hack around an interaction between the borrow checker and the output of a function constructed using dot syntax.
No. clone() calls std::clone::Clone::clone. For many std collections that means deep/recursive copy.
For custom data structures, it can mean anything. It depends entirely on your implementation of the Clone trait.
connection.write_all(data)
Where data could be an argument that impls ToOwned or Into so that it would either use the object you pass in (if by value) or implicitly clone it (if by reference).Basically this looks more like an API design problem than a limitation of the language.
A normal writer API would look like one of the variations:
Writer<T>::new(&connection).write(&data)
Writer<T>::new(&mut connection).write(&data) // if conn needs changes.
It's rare to unwrap(), which can cause a crash at runtime, but to handle the result. E.g. to write more data if the previous write is successful. let mut writer = Writer<T>::new(&connection);
let mut written_len = 0;
written_len += writer.write(&data1)? // ? returns the err if it's Err
written_len += writer.write(&data2)? // or unwrap the result value
written_len += writer.write(&data3)?
As you can see, "writer.write(&data1)?" is equivalent to the C++ version.The actual code we were working on involved functions returning closures with mutable captures, so the borrow checker was especially persnickety.
> functions returning closures with mutable captures
That sounds like another bad design, but to each his own.
It's not difficult to arrive at the caricature of baroque generic code if you combine lack of knowledge with miscommunication. The knowledgeable coworker should be aware that a writable object implements the Write trait, and know, or find out, the signature of the Write::write() method. Even fully generic, a function accepting a connection and returning the result of writing a block of data is not too gnarly:
use std::io::{self, Write};
fn write_data<W: Write, D: AsRef<[u8]>>(connection: &mut W, data: D) -> io::Result<usize> {
connection.write(data.as_ref())
}
No unwraps, no clones. Because they're not necessary here. But someone has to know the language and the idioms. Even your "easy" C++ code depends on knowing that write() returns zero on success, and that integers can play the role of booleans in conditions.*I totally agree with you that folk writing code need to understand the semantics of what they're building on top of. Humans and now AI models have a great capacity for generating tons source code without understanding the semantics, though.