My first cup of Rust

It all started with an informal chat with my friend Anthony. We were talking about languages, and I said that I preferred compiled ones. He then went on to mention Rust. We admitted that we were too afraid to learn it because of its perceived complexity.

After the chat, I thought about it, and I wondered why I didn’t check by myself. I did. And I became interested.

There are tons of resources on the Web on how to learn Rust. This post is a memo of the steps I followed. It’s probably less structured than my other posts but I hope you might benefit from those notes anyway.

Read in full here:

This thread was posted by one of our members via one of our news source trackers.

2 Likes

Corresponding tweet for this thread:

Share link for this tweet.

1 Like

Hmm, not a fan of their initial code:

pub fn find_largest_group(groups: Vec<Group>) -> Option<&Group> {
    groups
        .iter()
        .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
}

My gut reactions:

  1. What on earth is with the partial_cmp dance, just use > or whatever… >.>
  2. Why is max_by being used when max_by_key is what should be used here, there’s no point to all that at all, just replace that whole max_by(...) stuff with max_by_key(|g| g.members.len()) and be done with it…
  3. Uh, why is it trying to return a reference to something that’s locally on the stack/arguments? That will go away and the memory reclaimed when the function returns, thus a dangling reference, which in most referential stack languages (C/C++/whatever) will do… surprising things, but thankfully rust won’t compile it, which indeed their next example shows…

…skip a few bits…

So they ended up fixing it by writing it to:

pub fn find_largest_group<'a>(groups: &'a Vec<Group>) -> Option<&'a Group> {
    groups
        .iter()
        .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
}

First of all, the lifetime is not necessary there, it can be elided. Second, the partial_cmp dance is still irritating. Third, thankfully passing in the main groups by a reference so you can actually return a reference to something in it now. And lastly fourth, why was it not mentioned that they reason to pass groups in as a reference is to fix trying to access deallocated memory?!? Instead it was fixed with just the thing of hence borrowing is not necessary, which was entirely wrong (as ‘now’ it is being borrowed, it was being moved before, not borrowed). Rust saved you from a major memory corrupting bug there… >.>

…skip some more…

Import paths. The Rust convention is to use structures’ full path but to use functions’ path last segment

Wut… no… >.>
I’ve not seen that done in any rust code unless disambiguation was necessary… >.>

… Ooooooo …

I think the author got mixed up with importing static functions defined on a module compared to defined in an implementation. What they did was absolutely not convention, however it would have been right if a was actually A and was an implementation of something, but their code was not.

…skip some more…

It’s a good idea to make both our model classes “debuggable”:

…no, it doesn’t make them “debuggable”, it just adds an implementation of Debug, which is nothing but a printer (to like a string) that gives you a rust’y form of the implementation of the value. It changes nothing about debuggability of it, which is all in your debugger, like gdb or whatever, which doesn’t use the Debug trait at all.

…skip some more…

And more issues but I have other stuff I need to do… ^.^;

1 Like