perror(3)
exit(3)
One of the most concerning thing about cargo
are the online crates and
crates.io. This rises similar problems to npm
and go
packages, which make easy a very apealing point: online packages. Now, at
this point anything you download, compile, run, etc from the internet has
some chance of having some kind of malicious code on it, whether to
profit or to prove a point.
cargo
makes everything easier by wrapping rustc
options on it, adding a
Cargo.toml
to easily configure and tweak behaviours, making it default for
your package.
One of the things that caught my eye really fast is how simple it is to handle
platform specifics with macros such as #[cfg]
and cfg!
. These help you
identify the OS the program is on: the first one serves similar to a CPP in C
in which only the
code that match the OS you specified will get compiled into the bin, the latter
is an actual expression evaluated at runtime1.
This is also servers for enabling/disabling features that a library may provide.
The best documentation for libraries that you can get. Even that, binary programs also get treated the same 1: I did that with racf, for example, it has help me a lot. , which improves redability and most important, intention.
I’m no expert, just like Errors it’s my first time in which I apply this kind of concepts in practice. Testing can even be done in documentation which is insane.
I really like that the compiler forces you to write correct code, as in
handling Option<>
and Result<>
(overall enumerated values). While the code
might look like a lot of match
es, it gives you the heavy lifting (of manually
handling every possible case) in order to prevent the magical
failures/errors. If something fails it’s very likely that you’ll know why.
let my_life = match get_mindset() {
Ok(o) => o, //Ok
Err(e) => get_partner() {//no mindset found.. Let's make one!
Some(s) => match s {
Partner::Bully => MindSet("scared"),
Partner::Lovely => MindSet("dreaming"),
Partner::FarFarFar => MindSet("sadge"),
Partner::Casual => MindSet("depressed"),
Partner::SoulMate => panic!(),
},
None => match get_family() { //maybe a family member?..
Some(s) => MindSet("expressive"),,
None => get_pet() { //you have no one :3
Pet::Dog => MindSet("Happy"),
Pet::Cat => MindSet("annoying!11"),
Pet::None => MindSet("work"),
}
}
}
}
I’ve never been this close to error handling hell in a language. Usually I just would:
if (something == NULL)
return
or just use !
operator:
2: This also works for checking negative values, one of the most simplest and
arcaics ways to inform an error happen, or, at least, that’s what I have seen
and been doing for a while :p.
if (!something)
return
When using libc calls, I’d use perror()
and exit()
. I may decide to give the user a some information about what happen rather than a perror()
string, in simple programs this is very trival to do. Even when the logic is complicated, that wouldn’t be a problem for me
3: Just call perror()
and exit()
dud.
, but using libraries it all came to hell..
In C
I encounter that enums where just another name for a value (number),
which caused problems when evaluating different errors: Error1
could be the
same value as HttpsErrorTlsDenied
and so on. Rust solved this, making enum
values unique, as in they don’t need to represent something.
Now I’m seeing some programmers use assertions instead, which could lead to more crashes but in the long-term gives the ability to prevent those bugs/errors/etc.
One of the most difficult things is to think how to handle and structure these.
A goood video that allow me to think about errors (as an error handler novice) using the rust programming language:
Rust Linz, January ‘22 - Error Handling in Rust - A Pragmatic Approach by Luca Palmieri
And a very good article about it: Error Handling In Rust - A Deep Dive