Go has chosen to omit assert(), because assert() is frequently misused they say. Antibiotics are also frequently misused, but that is not a good reason to prohibit them. The omission of assert() makes Go a non-starter.
Rust seems more promising, but it is still not to the point where I am interested in rewriting SQLite in Rust, though I may revisit this decision in future years.
Some current reasons to continue to prefer C over Rust:
(1) Rust is new and shiny and evolving. For a long-term project like SQLite, we want old and boring and static.
(2) As far as I know, there is still just a single reference implementation of rustc. I'd like to see two or more independent implementations.
(3) Rust's ever-tightening interdependence with Cargo and Git is disappointing.
(4) While improving, Rust still needs better tooling for things like coverage analysis.
(5) Rust has "immutable variables". Seriously? How can an object be both variable and immutable? I realize this is just an unfortunate choice of terminology and not a fundamental flaw in the language, but I believe details like this need to be worked out before Rust is considered "mature".
A small syntactic sugar you can trivially implement yourself makes Go a non-starter?
Go doesn't include assert in the language because you're supposed to do better than assert. Assert easily allows lazy programmers to let their programs freely crash without properly handling error conditions. Go prevents you from compiling with unused variables, and that combined with the Go documentation goes a long way towards teaching new Go programmers how they're expected to work.
And neither Go nor Rust could possibly be good fits for SQLite. A Go hello world is bigger than all of SQLite while an idiomatic Rust one is on par, and neither's nearly as portable as the current C implementation, one that is both programatically and battle-tested like pretty much nothing else in the world.
> Assert easily allows lazy programmers to let their programs freely crash without properly handling error conditions.
This is what he meant by misuse. Properly-used assertions are meant to document and check conditions that were thought to be impossible by the developer. Not just unlikely, or illegal, but impossible. If a condition is possible, and you check it with assert, that's a bug.
I came to detest assert when I was working on a project with another guy, who used it generously, as a substitute for assertions in (non existing) unit tests. Nothing would annoy me more than working on my code, running it, and having all sorts of weird assertions pop up all over the place from this guy's code.
Those are panic territory, which carries a different connotation than the word assert (which has very likely influenced in its very widespread misuse).
>Go prevents you from compiling with unused variables, and that combined with the Go documentation goes a long way towards teaching new Go programmers how they're expected to work.
Things like this make me not want to use a language. Want to comment a=b; to a=3;//b temporarily? Too bad, either assign b to 3 or comment out b too, and if b was the only variable to make use of c, same for c, and so on. Same obnoxious nonsense as Java not letting unreachable code exist, making me have to comment out the rest of the function body if I want to put in a return in the start to test something, which happens often enough that it's a pain.
That mild inconvenience (which I almost never face while writing Go code after getting accustomed to the language and getting my editor to run goimports on save) has a big RoI in safety and program quality, which are much loftier goals than short term code-writing convenience.
> (5) Rust has "immutable variables". Seriously? How can an object be both variable and immutable?
Variables have been called variables since the dawn of time, i.e., the lambda calculus, which doesn't even have assignment. The name derives from the idea that for every invocation of a function, a variable in its definition may be bound to a different value, hence it "varies" at runtime.
To elaborate slightly, there's three components here:
let x = 5;
let mut y = 6;
The let statement binds a variable to a value:
* x and y are the variables
* 5 and 6 are values
* let does the binding
You can have an immutable binding, like x, or a mutable binding, like y. But most people turn "a bound variable" into "a variable" (or "an immutable variable") and "a mutably bound variable" into a "mutable variable".
I was trying to teach myself some Rust and found the state of the documentation to be very frustrating. The core language is decently documented with the manual, but the standard library documentation was out of date in many places, most annoyingly in the first few hits on Google.
I found 5 different ways to read a file on Google, and only one of them still worked. Plus I saw the release notes on the newest version that the syntax that worked is now obsolete in favor of a new operator.
The docs should never be "out of date" as in not working, though some parts don't have more than type signatures yet. Working on it. Please file bugs if something is not working, or swing by #rust-beginners, we love to help!
I was trying to read a file one line at a time (reading only the first few lines of a very large file), and it turned out to be somewhat difficult as the built-in functions seemed to be really keen on operating on the entire file at once.
You still have to be a bit careful about finding old posts and old docs on the internet about Rust, given that many APIs have only been stable for a short while.
In general, unless you know your source is up to date, I'd recommend ignoring the internet at large completely when it comes to Rust APIs and just focusing on the official docs for the release that you're using. They're plenty good enough, though you do have to get used to navigating them.
Really? I read the documentation for file I/O directly out of the Rust online docs and put together a complete serialization module for a project I'm working on. It was actually quite straightforward.
> (3) Rust's ever-tightening interdependence with Cargo and Git is disappointing.
I can see the latter, but why the former? Package management that has understanding of language dependencies is a huge productivity booster.
> (5) Rust has "immutable variables". Seriously? How can an object be both variable and immutable? I realize this is just an unfortunate choice of terminology and not a fundamental flaw in the language, but I believe details like this need to be worked out before Rust is considered "mature".
A variable/binding is mutable, the object is not. I don't see the problem.
That's an interesting take. I don't think I've heard that complaint about go from anyone (other than you, I think, in a previous HN conversation). I've worked on code that had assert (Squid before the C++ rewrite, and it used assert correctly to the best of my knowledge), but I never considered it vital to the end result.
Have you read about panic (https://blog.golang.org/defer-panic-and-recover)? I'm not meaning to assign you homework, as I know you know more about this than I do, I'm just curious what about assert makes it mandatory for you...panic in go does require you to write your own error check (presumably just an if, for assert-like behavior, but you could do more complex error-handling).
All of your other comments are certainly valid reasons to choose C. Though I like cargo, and I suspect C would be well-served by something similar.
Rust seems more promising, but it is still not to the point where I am interested in rewriting SQLite in Rust, though I may revisit this decision in future years.
Some current reasons to continue to prefer C over Rust:
(1) Rust is new and shiny and evolving. For a long-term project like SQLite, we want old and boring and static.
(2) As far as I know, there is still just a single reference implementation of rustc. I'd like to see two or more independent implementations.
(3) Rust's ever-tightening interdependence with Cargo and Git is disappointing.
(4) While improving, Rust still needs better tooling for things like coverage analysis.
(5) Rust has "immutable variables". Seriously? How can an object be both variable and immutable? I realize this is just an unfortunate choice of terminology and not a fundamental flaw in the language, but I believe details like this need to be worked out before Rust is considered "mature".