Logo
Logo
46 results for
  • I used to think generics were fancy academic stuff that you’d rarely need in practice. Then I wrote my third function that was identical to a previous one except it operated on f64 instead of i32. Generics aren’t luxury features — they’re how you stop writing the same function five times for five different types.

    The Problem Generics Solve

    Without generics, you write duplicate code:

    fn largest_i32(list: &[i32]) -> &i32 {
        let mut largest = &list[0];
        for item in list {
            if item > largest {
                largest = item;
            }
        }
        largest
    }
    
    fn largest_f64(list: &[f64]) -> &f64 {
        let mut largest = &list[0];
        for item in list {
            if item > largest {
                largest = item;
            }
        }
        largest
    }
    
    fn main() {
        let ints = vec![34, 50, 25, 100, 65];
        let floats = vec![3.4, 5.0, 2.5, 10.0, 6.5];
    
        println!("Largest int: {}", largest_i32(&ints));
        println!("Largest float: {}", largest_f64(&floats));
    }
    

    These functions are identical except for the type. Generics let you write it once:

    Rust tutorial rust beginner Created Mon, 08 Apr 2024 20:00:00 +0000
  • Traits are the mechanism I miss most when I leave Rust. They’re interfaces without inheritance, type classes without the math, and the foundation of every abstraction in the language. If structs define what data is, traits define what data does.

    What Is a Trait?

    A trait defines a set of methods that a type can implement:

    trait Greet {
        fn hello(&self) -> String;
    }
    
    struct Person {
        name: String,
    }
    
    struct Robot {
        id: u32,
    }
    
    impl Greet for Person {
        fn hello(&self) -> String {
            format!("Hi, I'm {}!", self.name)
        }
    }
    
    impl Greet for Robot {
        fn hello(&self) -> String {
            format!("UNIT-{} OPERATIONAL", self.id)
        }
    }
    
    fn main() {
        let person = Person { name: String::from("Alice") };
        let robot = Robot { id: 42 };
    
        println!("{}", person.hello());
        println!("{}", robot.hello());
    }
    

    The trait Greet declares that any implementing type must have a hello method. Person and Robot each provide their own implementation. Different types, same interface.

    Rust tutorial rust beginner Created Sun, 07 Apr 2024 15:45:00 +0000
  • Goroutines make concurrency easy to start, but easy to start isn’t the same as easy to get right. The first time I ran multiple goroutines that touched shared data, I got a data race — a situation where two goroutines read and write the same variable at the same time, producing unpredictable results. The Go race detector caught it immediately, but I still had to understand how to fix it.

    Go tutorial golang beginner Created Sat, 06 Apr 2024 00:00:00 +0000
  • The first time I added a dependency in Rust, I was shocked. Add one line to Cargo.toml, run cargo build, and it downloads, compiles, and links everything automatically. Coming from C++ where dependency management is a special circle of hell, Cargo felt like cheating.

    What Is a Crate?

    A crate is a compilation unit in Rust — the smallest amount of code the compiler considers at a time. There are two kinds:

    Rust tutorial rust beginner Created Fri, 05 Apr 2024 10:30:00 +0000
  • Rust’s module system confused me for longer than I’d like to admit. I came from Go, where packages map directly to directories. Rust’s module system is more flexible — and more confusing as a result. But once you understand the mental model, it’s actually quite elegant. The key insight: the file system doesn’t define the module tree. You do.

    Modules in a Single File

    The simplest case — modules defined inline:

    Rust tutorial rust beginner Created Wed, 03 Apr 2024 14:00:00 +0000
  • Before Go modules existed, managing dependencies was genuinely painful. People used all sorts of third-party tools with their own conventions, and getting a new contributor up and running on a project could eat half a day. I started learning Go after modules became the standard, and I took for granted how smooth the experience was — until I read the old blog posts describing what came before. It made me appreciate go mod init in a way that’s hard to describe.

    Go tutorial golang beginner Created Tue, 02 Apr 2024 00:00:00 +0000
  • Exception-based error handling has a fundamental flaw: you can’t tell by looking at a function signature whether it might throw. Go fixed this by returning (value, error) tuples, but then you’re back to forgetting to check the error. Rust’s Result type gets it right — errors are values, and the type system makes them impossible to ignore.

    The Result Type

    // Built into the language:
    // enum Result<T, E> {
    //     Ok(T),
    //     Err(E),
    // }
    

    Result<T, E> is either Ok(T) (success with a value) or Err(E) (failure with an error). You’ve seen Option<T>Result is similar but carries error information when something goes wrong.

    Rust tutorial rust beginner Created Mon, 01 Apr 2024 08:45:00 +0000
  • In my experience, about 80% of all data structures in real programs are either lists or key-value maps. Rust nails both of them. Vec and HashMap are fast, safe, and ergonomic — and once you know these two plus HashSet, you can build almost anything.

    Vec — The Dynamic Array

    Vec<T> is Rust’s growable array. It stores elements contiguously on the heap, like ArrayList in Java or std::vector in C++.

    Rust tutorial rust beginner Created Sat, 30 Mar 2024 11:15:00 +0000
  • In most object-oriented languages, data and behavior are bundled together inside classes. Rust separates them — you define data with struct (or enum) and attach behavior with impl blocks. This separation is cleaner than it sounds. You can add methods to a type from anywhere, not just its original definition. And there’s no inheritance tax.

    Your First impl Block

    #[derive(Debug)]
    struct Rectangle {
        width: f64,
        height: f64,
    }
    
    impl Rectangle {
        fn area(&self) -> f64 {
            self.width * self.height
        }
    
        fn perimeter(&self) -> f64 {
            2.0 * (self.width + self.height)
        }
    
        fn is_square(&self) -> bool {
            (self.width - self.height).abs() < f64::EPSILON
        }
    }
    
    fn main() {
        let rect = Rectangle { width: 10.0, height: 5.0 };
    
        println!("Area: {}", rect.area());
        println!("Perimeter: {}", rect.perimeter());
        println!("Is square: {}", rect.is_square());
    }
    

    The impl Rectangle block defines methods for the Rectangle type. Inside the block, &self is a reference to the instance the method is called on. It’s equivalent to self: &Self, where Self is an alias for Rectangle.

    Rust tutorial rust beginner Created Thu, 28 Mar 2024 17:30:00 +0000
  • Sliding window problems have a tell: the problem asks about a contiguous subarray or substring, and there’s a constraint that makes the brute force obvious but slow. When I was interviewing at a mid-size fintech that fancied itself FAANG-adjacent, I got a stock price problem in my first round. I almost panicked — “is this dynamic programming?” It wasn’t. It was a sliding window in disguise, and once I saw it, the solution wrote itself in about four minutes.

    fundamentals interviews Created Thu, 28 Mar 2024 00:00:00 +0000