Conversation

Toke Høiland-Jørgensen

Impressions learning Rust
Show content
I've been meaning to sit down and learn Rust for a while, and have made a few attempts, but it never seemed to click in a way that stuck.

Well, the holidays have afforded me with several days in a cabin in Norway with no particular plans, which nicely lent itself to giving this another go.

Although I obviously haven't mastered the language yet, I do feel like it has clicked in a way that it hasn't before. I figured I'd share a couple of impressions from the experience here.

1/
2
8
16
Impressions learning Rust
Show content
First of all, I feel like the Rust ecosystem has significantly improved since the last time I tried this a couple of years ago: The compiler error messages are more helpful, documentation is better, common libraries are more comprehensive in their functionality. This is all very helpful for someone new to the ecosystem!

2/
1
0
1

Toke Høiland-Jørgensen

Edited 2 days ago
Impressions learning Rust
Show content

Another thing that helped me was to start with something other than a complete beginner’s tutorial.

The Rust for C Programmers book is a great resource for someone with existing C experience; it explains the core Rust concepts concisely and in a way that makes it easy to lookup things as needed.

The other resource that was very helpful was the Blessed.rs curated list of common crates.

3/

1
0
3
Impressions learning Rust
Show content
On the subject of common crates, I am really impressed with the quality of the Rust libraries I ended up using for my small application (a simple command line utility that does dynamic DNS updates).

The clap and serde libraries for command line parsing and data (de)serialisation are great examples of this.

Simply define some structs, sprinkle a couple of macros across the members, and bam! Full featured command line argument parsing and YAML config file parsing, with the results being completely type safe and validated. All easily grok'able from the crate docs, that also have great examples to work from. Impressive!

4/
1
0
1
Impressions learning Rust
Show content
Speaking of type safety - the Rust type system is obviously one of the things that takes a while to wrap your head around. But once you do, its power soon becomes apparent!

Especially the various safe conversion functions that can convert types to each other with from/into/parse.

Parsing an IP address? Just specify an IP address-typed variable and assign string.parse() to it, and presto! the compiler will figure out the right parser function to call, and you'll end up with the right type of variable (you still have to handle errors, though).

5/
1
0
1
Impressions learning Rust
Show content
Coming from C, error handling is another thing that takes a little getting used to. I started out doing the same thing I would do in C: have each function log an error if something goes wrong, and then return an error code.

But in Rust, you can attach the error message to the error code! With a little help from the 'anyhow' crate this becomes really easy, and you can just return errors all the way up the call stack, and if you also return them from the main function, Rust will helpfully print an error message and exit non-zero.

(For libraries you'd want typed errors, but for a CLI app like I was building, this pattern of just bubbling up the error messages works really well. The context/with_context helpers from the anyhow crate help where the default errors are not too helpful).

6/
1
1
3

Toke Høiland-Jørgensen

Edited 2 days ago
Impressions learning Rust
Show content
In retrospect, I think that one of the hurdles coming to Rust from C is that Rust forces you to do things right wrt representing everything with the right types, and manipulating them according to the rules of the type system. Which requires wrapping your head around a lot of different things at the same time before you can make any progress.

But once you *do* wrap your head around it, you get a kind of phase change feeling: suddenly things go from being obtuse and frustrating to being straight forward, and you really start to feel the power of the type system work in your favour. Which is very cool, and really shows the power of the language!

Oh, and the "when it compiles, it works" thing is definitely real; I spent very little time debugging weird runtime errors once things were actually compiling!

7/
2
2
5
Impressions learning Rust
Show content
If anyone is interested in the tool I built for this exercise, it's a simple DNS updater tool (for RFC 2136 updates):

https://github.com/tohojo/update-dns

I spent quite a bit of extra time on polish to make the code shorter and more readable as I learned more about various Rust constructs, but I have no idea if I succeeded in getting anywhere close to 'idiomatic Rust', if such a thing exists. So comments from more experienced Rustaceans are very welcome!

8/
1
0
2
Impressions learning Rust
Show content

@toke taking several "bounces" before one starts getting it does seem to be a common thing with Rust

1
0
0
Impressions learning Rust
Show content

@toke Have you used clippy? Clippy is fantastic at showing you better ways of doing what you're already doing. It's like having an experienced rust developer review your code for you and point out useful tricks.

1
0
0
Impressions learning Rust
Show content

@toke Coming from C, I foolishly expected that `u8`s would wrap around when doing `u8::MIN-1`, or... go back to 0 when doing `u8::MAX+1`.

But of course not, all this is learned undefined behaviour, and things like

```myu8 = max(myu8-1, 0);```

to do some clamping don't even compile.

Instead, there are defined methods to do this explicitly instead, such as saturating operations, e.g. https://doc.rust-lang.org/stable/std/primitive.u8.html#method.saturating_sub,

```myu8 = myu8.saturating_sub(1);```

(Look, ma, no `max`!)

1
0
0
Impressions learning Rust
Show content
@isomer I have not! Will give that a shot, thanks for the tip :)
0
0
0
Impressions learning Rust
Show content
@shtrom haha, yeah, didn't run into anywhere that I needed to wrap anything, but I can certainly see why it makes sense to avoid that by default. Humans don't generally think about numbers as wrapping!

(To be slightly pedantic, *unsigned* integer wrapping is not strictly speaking undefined behaviour in C, only signed[0], but that doesn't mean it can't lead to surprising bugs...)

[0] https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Integer-Overflow-Basics.html
0
0
1
re: Impressions learning Rust
Show content
@pmmeurcatpics yeah, not surprising! Certainly tracks with the experience I mentioned in the last post: you sorta run into this brick wall of type representation which you have you scale before you can do really useful things. Takes a bit of persistence to do, I suppose...
0
0
1