Rust from a Gopher - Lessons 12..14

Hello and welcome to the eighth post in my series about learning Rust. In case you want to hit it from the start, here’s a link to the first one! This entire series covers my journey from being a completely land-locked Gopher to becoming (hopefully) a hardened Rustacean, able to skitter the hazardous seabed of any application safely.

Excitedly, I managed to make my way through three chapters of The Book recently. They were short, and so were my thoughts on them.


12. An I/O Project: Building a Command Line Program

This chapter was about finally using Rust to build something. That something is a very rudimentary version of grep, but it’s a real thing and I’ll take it. Overall I found the structure of this chapter good, you start with a fairly chunky grep implementation, then via the lessons you’ve learned from The Book, you refine it. It was a calming experience and helped reinforce the lessons learned (that are terrifyingly already fading away in my mind).

You don’t learn anything new in this chapter, except for the eprint! macros. Onto the next chapter!

13. Functional Language Features: Iterators and Closures

Closures

As described, this chapter introduces you to some functional programming features of Rust, mainly using different types of closures. Go is similar to Rust in that is has some functional features, like closures, too. It’s been a while, but I did a coursera course in 2014 on functional programming. It was a lot of fun and exposed me to thinking about programming in a way quite orthogonal to what I was used to. We used ML and Racket and that class primarily. Since that class though I haven’t really been back into FP.

Let me begin by saying that this chapter’s example frustrated me a lot. It wasn’t until about 85% of the way through the closures section did I realize what the example was doing. It was just a generalized memoization struct! Maybe I’m dumb, but I just kept expecting to use closures from the get go to capture the environment. Instead, it was mainly about using lambdas. I ended up writing a basic Go version of the example for kicks too.

On the positive side, type inference on closure params is really nice to have (yes: this is my per-blog nod to Rust type-inference). I get that it’s hardly magic, but it’s still way better than what Go’s type inference offers.

Iterators

Pleasingly, this chapter took time to dive into the stdlib’s Iterator Trait. I am staggered by the range of provided methods you get, just from implementing next to satisfy the Trait. What’s even cooler is that you can totally override any of the provided methods with more efficient implementations when it makes sense to for your struct too.

Look at how beautiful your code can become, by chaining iterator methods and using lambdas from the standard library.

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents
        .lines()
        .filter(|line| line.contains(query))
        .collect()
}

It almost makes me feel physically relieved when I imagine myself writing this code, compared to Go. What makes it even spicier is that the Book tells us performance is 100% matched with hardcoded-loop style implementations, so you can write like this with zero guilt.

14. More about Cargo and Crates.io

Here we learn about using Cargo/Crates.io from a sharing perspective. I enjoyed this chapter and look forward to leaning on many community crates in the near future.

Package Docs

The first thing I did when finding out about crate documentation comments was make some in my IDE and then hit enter. Gloriously, Intellij’s Rust plugin knew what I was up to and made a new line prefixed with ///

Nothing is better than documentation with examples. But nothing is worse than examples that don’t work because the code has changed since the documentation was written.

This line made me chuckle. Thanks Book.

Pause, before Publishing

Be careful when publishing a crate because a publish is permanent. The version can never be overwritten, and the code cannot be deleted.

Oh wow, that is serious. I wonder if there have ever been exceptions to this rule. It’s good that you can cargo yank a version to prevent people from using bad versions of your code. I like that. But it would still suck for the people who accidentally pushed credentials or something sensitive to crates.io - the mark is permanent.

Install the things

cargo install - I finally have ripgrep on my computer


A final note about this chapter; I appreciated it going over pub use in more depth. This helped me solidify the use-case of re-exporting your crates to build better APIs.

En. Sum.

These chapters were not rich with new concepts, and I liked being able to speed up a little here. In all honesty I cannot wait to be done with The Book, so I can write terrible programs and then rewrite them, as I learn about Rust in real life. There’s only six chapters remaining from this point. I think I may end up just summarizing my perspectives on them in a single blowout blog, as the learnings are getting deeper and as such I have less obvious points to compare the language features to. No point in dragging it out from here on!

Until next time, cya.

comments powered by Disqus