After gaining a fairly reasonable comfort level with the syntax of rust, I decided to embark on my preferred way of learning. Doing. I think I learned a lot more about the pitfalls of rust with the training wheels off. A seasoned rust programmer or a well educated newbie may not have made the same falls I did. A reminder that this post is going to be Opinion, do not take my opinion as a representation of fact.
Perhaps I made a bit of a huge mistake undertaking a project where I have to handle fake times in rust. It’d have been an annoying project in C too, but nonetheless, My systems programming project was a timekeeper for my RPG sessions. My goal was simple, but I feel it really taught and showed me the holes in my understanding.
Documentation, mathematics vs programming
You have to know what to ask, where to look, and what you’re actually looking for to find a lot of the documentation in rust. The documentation is right there but its hard to find. Using a community discord might be a good option but that’s really not for me1.
For me? my first real wall was trying to find out how to do integer modulo and floor. Both of these are fairly simple questions to answer if you know where exactly to look. As someone who’s been coding rust for… not even a week… That was not me, In the end venting about this on my discord’s #tech channel was what got me the right answer.
These are easy questions so why were they so hard to answer? Because I didn’t know two key important things
- rust doesn’t always call things the same thing that standard programmer convention does.
- rust std documentation often has the info, you need to really search it first and assume what you are looking for exists.
If I had known these two things going in, I wouldn’t have gotten frustrated. I would have just found the things. Instead I used a search engine, like I think most people do when trying to find documentation for a language. This was painful, the game Rust, and rust being a fairly quickly moving target made this much more difficult than other languages.
The modulo operator
% is a great example of where rust doesn’t use a
typical programmer convention, This is described as the “remainder”
operator. This is mathematically correct,
% in other languages is
really remainder too. If you need a real modulo that handles negative
numbers correctly, you have to write your own. Thing is, I don’t think
most programmers actually know the difference2. When I searched for
info on rust modulo… I got posts telling me rust didn’t have one
built in, not “Rust implements
% just like C, as a remainder
function.” or recognising that typical bit of convention at all. This
ended up confusing me immensely. Compiler errors I got implied
didn’t exist (see the next section on compiler errors for more on that
front), but it was actually that both sides needed to match. Blog
posts and stack overflow implied modulo didn’t exist unless you
implemented it. I was about ready to give up there.
.floor() method is a great example of knowing where you need to
read the docs. If you search for it in a typical search engine, you
end up getting a rather old crate3. If I had known it was a method
f64 and i should search the docs for it instead of
looking for a
floor() function, I would have known
exactly what documentation to look for, This is quite a chicken/egg
The compiler errors are not as clear as evangelists think they are.
Rust evangelists often praise the compiler errors and warnings as being a “killer feature”. The thing is, They still suffer from the same problems as any LLVM compiler does. You will get confusing errors that you cannot solve by just reading it. Over time you will familiarise yourself with certain kinds of errors, you will learn what it means despite what it says. You are not the same as a new programmer.
A new programmer won’t understand why
? causes a type error the
first time it comes up. A new programmer may not understand what they
are doing wrong with the mod keyword. Even as you work through the
book. Only with making every single possible mistake can you
understand what you did wrong, often including having to search an
error because it makes no sense. The errors I’ve seen so far that do
make sense? those are often the same kinds of errors that LLVM based
compilers like clang actually catch too.
This isn’t really a fault of the compiler, compilers don’t know what you mean, they can make some assumptions and try to be helpful but in the end, if they could do what you mean, without you clarifying by fixing your code, they would just have done it in the first place.
Crates for everything, stable APIs be damned.
In rust, nearly everything you could possibly want is a crate. This isn’t a bad thing per say, I come from perl and everything there is a perl module and uploaded to CPAN. What’s scary is the amount of things that you would think are included as a helper… but aren’t. Basic things like unix signals (to catch SIGTERM for example) are relegated to crates instead.
Crates have features, you can read something and not enable a required
feature, Serde and Clap but have a
derive feature that has to be
enabled, the examples don’t always make it clear this may require a
feature flag or an additional module. This was actually a cause of a
lot of the compiler errors that made no sense.
Crates seem to be a moving target that hurts to follow. I mentioned i started with a book this time, in that book we learned to use clap. What it did was pretty neat, a programmatic method of handling args for your program. It does still do this. The thing is, the API changed a while ago, and they only promise not to change the api every 6-9 months. I had to relearn how to use it. While this problem is not unique to Rust it does seem to be a common issue I’ve noticed as clap wasn’t even the only one that did this.
extern, libc, and reality
Talking with someone who jumped on the rust train earlier than most
has taught me one massive thing. The hypetrain around rust often
doesn’t reflect reality. A good example of this is the “rust std
completely 100%ly replaces libc” lie. This is only true on
targets, and even then you might be linking your own C stuff for
that. It makes sense when you think about it, If you were required to
use rust for everything, rust would be far less useful. The ability to
interop with libraries and programs written in C and C++ is one of the
things that makes it compelling.
It’s nice that I can use things like libc or Qt or ncurses. These are mainstays of development in a world that has been doing GUI computing in the mainstream for a good 40 years. We have tools that work, and moving away from them will be a more difficult reality than allowing us to use what we already got. People are even still using openssl with rust. They probably shouldn’t be, but nonetheless it is there and ready to use.
I did not poke at rust for web programming. I will use Elixir or Ruby for this pretty much always. It’s what fits my use cases the best and I see no point using a language like rust for this. I know rust has been seeing use in this space, perhaps if I find myself liking it further on down the line I might experiment with something that isn’t fast enough or is too memory intensive in elixir or ruby. Doubt it though. This section is here mostly to address this “blind spot” for the reader.
Embedded Programming [Microcontrollers]
Rust on my microcontrollers for the most part became a bit of a nonstarter. While I found countless modules for every single chip, I didn’t find HALs that were still in development for what I have. Rust feels quite incomplete in this space, people will say “but there is a crate for that”, but a concerning amount of times it’s just a svd2rust conversion without a HAL. Due to this lack of hardware, I ended up writing no code and looking at and compiling examples.
I was rather interested in rust on esp8266, it was one of the situations I saw rust doing very well in. The problem is, I don’t have time for “experimental” code for my projects. When I saw that the ESP8266-hal crate had been moved on from to focus on the ESP32 stuff. I have no problem with focusing on the ESP32, I just don’t own one and didn’t want to source one for experimenting with rust.
The amount of code it does generate is quite impressive, It’s about on par with C, that said I did not have a quite a fair test because the C I had on hand to compare it was for a different more complex mcu. I couldn’t find examples and code for the EXACT boards I have in rust either [well, that didn’t use C as well], and I didn’t really get to see if it’d flash and it’s real size…
I can see how and why people like rust. My opinion on it is softened but I don’t see myself reaching for it first. I can see its potential. I’m going to keep my eye on it, and maybe with some age and time… things will be less in a state of flux.
Thanks to the rustaceans I sent my drafts to to catch factual errors. If you find a factual error (read: not an opinion) that is not related to an updated version of rust in this post, You can try get ahold of me and I’ll probably fix it. I probably won’t update this beyond a few months due to the moving target-ness beyond saying things may have changed in a minor version.
This post is part of a series: Previous Article
Considering the point of view I have is fairly negative towards rust, I think a lot of people would be either far less likely to help me or far more likely to read my questions as directly confrontational. ↩
I’m sure that all of you college math/programming dual majors knew this, but I thought rust was supposed to be programming for everyone? ↩
Why does this even exist??? was older rust using libc for math functions? Was it just a toy? It didn’t seem to use generics even. ↩