--- description: Notes to self about learning rust created: 2026-07-22 --- [TOC] The take aways from [__The__ book on rust](https://doc.rust-lang.org/stable/book/) that took my knowledge from point A to B as primarily a Python developer. ## Chapter 2 ### Declaring variales `let` declares a variable in the local scope variables are immutable by default --- [*"The `::` syntax in the `::new` line indicates that new is an associated function of the String type"*](https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#:~:text=The%20%3A%3A%20syntax%20in%20the%20%3A%3Anew%20line%20indicates%20that%20new%20is%20an%20associated%20function%20of%20the%20String%20type) --- in object oriented we call a function on an object a method --- In rust you can reference the same object, and do a object.clone, similar to python --- ```rust use std::io; fn main() { println!("Guess the number!"); println!("Please input your guess."); let mut guess = String::new(); io::stdin() .read_line(&mut guess) .expect("Failed to read line"); println!("You guessed: {guess}"); } ``` I'm learning rust, why do we instantiate a variable with `String::new();` only to append something to it afterwards, is it functional or for legibility, reply concisely. In Rust, `String::new()` is the common “start with an empty owned buffer” pattern. read_line(&mut guess) needs a String you can mutate (grow) as input arrives, so you create an empty one first. It’s functional (you need an owned, mutable String to pass to read_line), and also idiomatic/legible because it makes the intent—“this will hold the user’s input”—clear. --- [Result enum states are called variants](https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#:~:text=Result%20is%20an%20enumeration%2C%20often%20called%20an%20enum%2C%20which%20is%20a%20type%20that%20can%20be%20in%20one%20of%20multiple%20possible%20states%2E%20We%20call%20each%20possible%20state%20a%20variant%2E) --- [Rust doesn’t yet include random number functionality in its standard library](https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#:~:text=Rust%20doesn%E2%80%99t%20yet%20include%20random%20number%20functionality%20in%20its%20standard%20library) [The specifier 0.8.5 is actually shorthand for ^0.8.5, which means any version that is at least 0.8.5 but below 0.9.0.](https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#:~:text=The%20specifier%200%2E8%2E5%20is%20actually%20shorthand%20for%20%5E0%2E8%2E5%2C%20which%20means%20any%20version%20that%20is%20at%20least%200%2E8%2E5%20but%20below%200%2E9%2E0) ## Chapter 3 ### Looping chars ```rust fn main() { for n in 1..u32::MAX { let c: char = match char::from_u32(n) { Some(j) => j, None => { // println!("Can't get number for char value {n}"); continue; } }; // print!(" {n} {c}"); print!("{c}"); } } ``` Keeps trying with ints that don't have a unicode char > The rust book states: [*"Unicode scalar values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive"*](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html#the-character-type:~:text=Rust%2E%20Unicode%20scalar%20values%20range%20from%20U%2B0000%20to%20U%2BD7FF%20and%20U%2BE000%20to%20U%2B10FFFF%20inclusive) Coming back to this after the end of chapter 3: ```rust fn main() { for n in 1.. { let c: char = char::from_u32(n).expect(&format!("Can't get number for char value {n}")); print!("{c}"); } } ``` ```console thread 'main' (177732) panicked at src/main.rs:6:17: Can't get number for char value 55296 ``` ```rust fn print(char: u32) { let char: char = char::from_u32(char).expect(&format!("Can't get number for char value {char}")); print!("{char}"); } fn main() { for n in 0..0xD7FF { print(n); } for n in 0xE000..0x10FFFF { print(n); } } ``` Finally writing some rust i must admit that i find rusts compiler errors are really friendly, the syntax is plesent and legible, and leads you to handle errors. ### Assignments #### Temperature converter ```rust use std::io; fn celsius_to_fahrenheit(celsius: f64) -> f64 { (celsius * 1.8) + 32.0 } fn fahrenheit_to_celsius(fahrenheit: f64) -> f64 { (fahrenheit - 32.0) / 1.8 } fn main() { println!("Input temperature in the format: e.g: 22C or 30.4F"); let mut input = String::new(); io::stdin() .read_line(&mut input) .expect("Failed to read line"); let (temp, unit) = input.trim().split_at(input.len() - 2); let unit = unit.to_uppercase(); let temp: f64 = temp.parse().expect(&format!("Couldn't parse number from: {temp}")); println!("temp: {temp}, unit: {unit}"); let result_unit: char; let result: f64 = match unit.as_str() { "F" => { result_unit = 'C'; fahrenheit_to_celsius(temp) } "C" => { result_unit = 'F'; celsius_to_fahrenheit(temp) } _ => panic!("Unknown unit {unit}"), }; println!("{temp}°{unit} = {result}°{result_unit}") } ``` Asking an ai bot to give feedback ``` I'm learning rust, coming from python and some C programming, I've read the first 3 chapters of the rust book, which covers: ... ``` ``` Your code is solid Rust and it mostly avoids common beginner pitfalls from the book—but there are a few correctness/robustness issues and a couple “Rust-idiomatic” improvements. ``` It validates me, wow, what a supprise ![feel_the_validation.webp](feel_the_validation.webp) ``` 1. split_at(input.len() - 2) is brittle and can be incorrect because you compute the index from the untrimmed string length (so whitespace/newline can break the split). 2. Slicing by byte index is unsafe for general cases; indexing must land on a valid char boundary (your current approach assumes a fixed layout). 3. Parsing by “last 2 characters” assumes the unit is always exactly one character and located at a fixed position; inputs like 22 C, missing unit, etc., will fail or behave unexpectedly. 4. Your match works, but using result_unit + mutation in match arms is less idiomatic; returning both values directly is cleaner. 5. Using panic!/expect for invalid user input is fine for an exercise, but for real programs you’d prefer returning Result and printing a friendly error. If you want a robust fix: parse from let trimmed = input.trim(); and take the last non-whitespace character as the unit, then parse the remaining prefix as the number. ``` Nothing major, but let's address it to learn.
diff --git a/src/main.rs b/src/main.rs
index 9fee6af..2771e71 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,23 +15,17 @@ fn main() {
     io::stdin()
         .read_line(&mut input)
         .expect("Failed to read line");
+    input = input.trim().to_string();

-    let (temp, unit) = input.trim().split_at(input.len() - 2);
+    let (temp, unit) = input.split_at(input.len() - 1);
     let unit = unit.to_uppercase();

     let temp: f64 = temp.parse().expect(&format!("Couldn't parse number from: {temp}"));
     println!("temp: {temp}, unit: {unit}");

-    let result_unit: char;
-    let result: f64 = match unit.as_str() {
-        "F" => {
-            result_unit = 'C';
-            fahrenheit_to_celsius(temp)
-        }
-        "C" => {
-            result_unit = 'F';
-            celsius_to_fahrenheit(temp)
-        }
+    let (result_unit, result) = match unit.as_str() {
+        "F" => ('C', fahrenheit_to_celsius(temp)),
+        "C" => ('F', celsius_to_fahrenheit(temp)),
         _ => panic!("Unknown unit {unit}"),
     };
     println!("{temp}°{unit} = {result}°{result_unit}")
#### Fibonacci ```rust fn main() { const iterations: usize = 20; let mut prev: usize = 0; let mut cur: usize = 1; for _ in 0..iterations - 1 { let temp: usize = cur; cur = cur + prev; println!("{prev} + {temp} = {cur}"); prev = temp; } println!("{iterations}'th fibonacci number is: {cur}"); } ``` ```console ❮ cargo run a warning: constant `iterations` should have an upper case name --> src/main.rs:2:11 | 2 | const iterations: usize = 20; | ^^^^^^^^^^ | = note: `#[warn(non_upper_case_globals)]` (part of `#[warn(nonstandard_style)]`) on by default help: convert the identifier to upper case | 2 - const iterations: usize = 20; 2 + const ITERATIONS: usize = 20; | warning: `fibonacci` (bin "fibonacci") generated 1 warning (run `cargo fix --bin "fibonacci" -p fibonacci` to apply 1 suggestion) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/fibonacci a` ❮ cargo fix --bin "fibonacci" -p fibonacci error: the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files: * .gitignore (dirty) * Cargo.lock (dirty) * Cargo.toml (dirty) * src/ (dirty)    ~/projects/my_misc/rust/learning/3/fibonacci   master ?4 ─────────────────────────── ✘ 101   impure  13:54:46 ❮ cargo fix --bin "fibonacci" -p fibonacci --allow-dirty Checking fibonacci v0.1.0 (/home/user/projects/my_misc/rust/learning/3/fibonacci) Fixed src/main.rs (1 fix) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.13s ``` Again, really nice and native tooling ```rust fn main() { const ITERATIONS: usize = 20; let mut prev: usize = 0; let mut cur: usize = 1; for _ in 0..ITERATIONS - 1 { let temp: usize = cur; cur = cur + prev; println!("{prev} + {temp} = {cur}"); prev = temp; } println!("{ITERATIONS}'th fibonacci number is: {cur}"); } ``` ```console $ cargo run 0 + 1 = 1 1 + 1 = 2 1 + 2 = 3 2 + 3 = 5 3 + 5 = 8 5 + 8 = 13 8 + 13 = 21 13 + 21 = 34 21 + 34 = 55 34 + 55 = 89 55 + 89 = 144 89 + 144 = 233 144 + 233 = 377 233 + 377 = 610 377 + 610 = 987 610 + 987 = 1597 987 + 1597 = 2584 1597 + 2584 = 4181 2584 + 4181 = 6765 20'th fibonacci number is: 6765 ``` Correct ``` 89 1779979416004714189 + 2880067194370816120 = 4660046610375530309 90 2880067194370816120 + 4660046610375530309 = 7540113804746346429 91 4660046610375530309 + 7540113804746346429 = 12200160415121876738 thread 'main' (266042) panicked at src/main.rs:9:15: attempt to add with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` Currious, if i keep running it, i outgrow the instruction set of `usize` on x86_64, 19.740.274.219.868.223.167 > 2^64 (18,446,744,073,709,551,616) ```python-console >>> 7540113804746346429 + 12200160415121876738 19740274219868223167 ``` Python don't care, will have to keep that in mind. Useful for efficiency and embedded systems. #### Twelve days of christmas ```rust const DAYS: [&str; 12] = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh","eighth", "ninth", "tenth", "eleventh", "twelfth"]; const THINGS: [&str; 12] = [ "A partridge in a pear tree", "Two turtle doves and", "Three french hens", "Four calling birds", "Five golden rings", "Six geese a-laying", "Seven swans a-swimming", "Eight maids a-milking", "Nine ladies dancing", "Ten lords a-leaping", "Eleven pipers piping", "Twelve drummers drumming" ]; fn main() { for i in 0..12 { println!("On the {} day of Christmas, my true love sent to me", DAYS[i]); for j in (0..i + 1).rev() { println!("{}", THINGS[j]); } println!(); } } ``` ``` On the first day of Christmas, my true love sent to me A partridge in a pear tree On the second day of Christmas, my true love sent to me Two turtle doves and A partridge in a pear tree On the third day of Christmas, my true love sent to me Three french hens Two turtle doves and A partridge in a pear tree On the fourth day of Christmas, my true love sent to me Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the fifth day of Christmas, my true love sent to me Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the sixth day of Christmas, my true love sent to me Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the seventh day of Christmas, my true love sent to me Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the eighth day of Christmas, my true love sent to me Eight maids a-milking Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the ninth day of Christmas, my true love sent to me Nine ladies dancing Eight maids a-milking Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the tenth day of Christmas, my true love sent to me Ten lords a-leaping Nine ladies dancing Eight maids a-milking Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the eleventh day of Christmas, my true love sent to me Eleven pipers piping Ten lords a-leaping Nine ladies dancing Eight maids a-milking Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree On the twelfth day of Christmas, my true love sent to me Twelve drummers drumming Eleven pipers piping Ten lords a-leaping Nine ladies dancing Eight maids a-milking Seven swans a-swimming Six geese a-laying Five golden rings Four calling birds Three french hens Two turtle doves and A partridge in a pear tree ``` Again super error message for newcomers with helpful suggestion on how to remedy the issue.
   Compiling twelve_days_of_christmas v0.1.0 (/home/user/projects/my_misc/rust/learning/3/twelve_days_of_christmas)
error: missing type for `const` item
 --> src/main.rs:1:12
  |
1 | const DAYS: = ["first", "second", "third", "fourth", "fifth", "sixth",
  |            ^ help: provide a type for the constant: `[&str; 12]`

error: could not compile `twelve_days_of_christmas` (bin "twelve_days_of_christmas") due to 1 previous error
--- ## Chapter 4