[[!tag learning-rust]]

Re-reading Gentle introduction to Rust (GITR for short), the introduction and Chapter 1, "Basics". I'll be taking notes, to help me remember things. I'll note things that seem important or interesting, or new things I'm learning, or thoughts provoked by the reading material.

Introduction

  • GITR doesn't aim to reach all aspects of Rust, but to "get enough feeling for the power of the language to want to go deeper". Also, to make it easier to understand other documention, especially the Rust Programming Language book.

  • GITR doesn't seem to be dumbed down, but it does skip some of the details. That's fine.

  • Points at the Rust Users Forum, and the Rust subreddit. I've already subscribed to the subreddit RSS feed. I don't think I want to follow a web discussion board.

  • Also points at the FAQ, which I shall browser later.

  • While I don't disagree with the sentiment, GITR disses C a little more than I'd like.

  • Unifying principles of Rust:

    • strictly enforcing safe borrowing of data
    • functions, methods and closures to operate on data
    • tuples, structs and enums to aggregate data
    • pattern matching to select and destructure data
    • traits to define behaviour on data
  • GITR recommends installing Rust via the rustup script. I do wish Rust would get past that being the default.

  • I've already previously configured my Emacs to use rust-mode for .rs files. Seems to be OK.

  • Not entirly sure using rustc directly is a good idea in the long run, cargo seems like a better user experience, but it can't hurt to be familiar with both.

  • Refers to Zed Shaw. Ugh, even if the actual advice is OK in this instance.

Chapter 1: Basics

  • I don't think copy-pasting examples is a good habit, so I'll be typing in any code myself.

  • Note to self: println! adds the newline, don't include it in the string.

  • Compile-time errors for misspelt variable names? What sort of wonderful magic is this? After a couple of decades of Python, this is what I want.

  • For loops and ifs have fewer parens: nice.

  • New thing (I'd forgotten): ranges.

  • New thing: nearly everything is an expression and has a value, including ifs. Nice.

  • New thing: variables are immutable by default. This is another thing I like that Python lacks. It'll make it easier to manage large programs, where unintended mutation is a frequent source of errors for me. I expect it'll be a little annoying at first, but that I'll get used to it. I also expect it to save me at least 12765 hours of debugging in the next year.

  • New thing: type inference is also nice, but coming from dynamically-typed Python it feels like less of a win than it would if I came to Rust straight from C. However, I know from the little Haskell I learnt that type inference is crucial for a statically and strongly typed langauage to be comfortable

  • New thing: traits. These will be covered properly later, but I already know enough (from a previous partial read of GITR) that they're powerful and interesting. A bit like method overloading and subclassing, but not as messy. Traits also make things like operator overloading generic, and not as built-in as Python's __foo__ methods.

  • I like that Rust avoids implicit data type conversions, even from "safe" cases like integer to float.

  • Not sure the implicit return for functions, where the last executed expression in a function is the value returned for the function is something I'm going to like. We'll see.

  • Interesting: you can pass a reference to a constant?

  • I haven't got Rust docs installed, but I'll be using the online versions of those: https://doc.rust-lang.org/.

  • Arrays have a fixed size. Elements may be muted, but the array size is fixed at creation time. Array size is part of its type: arrays of different size have different types. Bounds checking for arrays can happen at least partially at compile-time.

  • New thing: [u32; 4] is the type of an array of four thirty-two-bit integers.

  • Slices are views into an array (or vector?). They're easier to pass as function arguments. Slices know their length, but since they're not fixed in size, different calls to a function may get slices of different sizes. A slice can be a view to only part of an array. Bounds-checking for slices is (at least primarily) at run-time.

  • New thing: &foo in Rust means "borrow foo".

  • New thing: slice.get(i) method to access a slice's element without panicing. Returns a value of type Option, which means it can return a reference to value (Some(&value)) or an indication of no value (None). This is safer than Python's None as the caller must always deal with both cases, in pattern matching. Also, safer than throwing and catching exceptions. However, calling option.unwrap() can still panic, so that's a potential trap. The unwrap_or method avoids that, though. The expect method allows giving a custom error message.

  • Vectors are re-sizeable arrays. They seem to "become slices" when passed as an argument to a function that expects a slice. The borrow operator does the type coercion. Vectors have handy methods: pop, extend, sort, dedup. The docs have more: https://doc.rust-lang.org/std/vec/struct.Vec.html.

  • Memory management in Rust is one of its stronger attractions for me.

  • New thing: iterators. A powerful concept I already know from Python. I have the impression they're even more powerful and used even more than in Python. It's interesting that GITR makes the point that iterators are more efficient than looping, due to fewer bounds checks. I like that Rust values efficiency.

  • Strings are complicates. No surprise, since they are by their very nature, because humans. Rust strings are UTF-8 strings. There's byte strings separately.

  • format! is a handy macro.

  • Having access to command line arguments and file I/O this early in the book is good.

  • New thing: closures. Similar to lambdas in Python. Powerful.

  • New thing: match. I liked pattern matching in Haskell. This is similar, but different. I like that you must handle all cases.

  • New thing: if let.

  • New thing: inclusive ranges, with three dots.

  • New thing: Result type. Similar to Option, but better suited for errors, where an error is not just None. The "built-in" Result wraps two values, one for Ok, the other Err. This gets a bit repetitive, so std::io::Result<T> is a type alias for Result<T, std::io:Error>. Shorter, easier to type.

  • New think: the ? operator to handle Result checking in a terser fashion that doesn't obscure the happy path. Only useable in functions that return a Result value.