🦉
Programming Notes
  • My Programming Notes
  • CKA Exam Preparation
    • Certified Kubernetes Administrator
    • Setup Minikube
    • Network Design Principles
    • Role-Based Access Control (RBAC)
    • Namespace
    • Resource Quota
    • Pod
    • Deployment
    • Deployment: Rollout
    • ConfigMap
    • Service
    • Service: kubectl expose
    • Pod: Resources Management
    • Pod & Container: Quality of Service Class
    • Pod & Container: Probes
    • Limit Range
    • Scaling: Manual
    • Scaling: Horizontal Pod Autoscaler
    • Persistent Volume & Claim
    • Secret
    • Ingress: Routing
    • Ingress: TLS
    • Ingress: Rate Limit
    • Ingress: Basic Auth
    • Ingress: CRD (Custom Resource Definition)
    • Job
    • CronJob
    • Mutli-Node Cluster
  • Golang
    • Generics
    • Context
    • Goroutines and Channels in Go
    • Goroutine: Concurrency vs Parallelism
    • Goroutine: Performance & Tradeoffs
    • JSON: omitzero
  • Rust
    • Arrays & Slices
    • Closures
    • Generics & Traits
    • Iterators
    • Run Code Simultaneously
    • String vs &str
    • Tests
    • Rustlings Exercises
      • Variables
      • Functions
      • If
      • Primitive Types
      • Vectors
      • Move Semantics
      • Structs
      • Enums and Matching Pattern
      • Strings
      • Modules
      • Hashmaps
      • Options
      • Error Handling
      • Generics
      • Traits
      • Lifetimes
      • Tests
      • Iterators
      • Smart Pointers
      • Threads
      • Macros
      • Quiz 1
      • Quiz 2
      • Quiz 3
  • Software Engineering
    • CAP Theorem
    • Circuit Breaker
    • Decoupling
    • GraphQL: Query Caching
    • HMAC Signature
    • Idempotency
    • Monolith VS Microservice
    • OWASP Top 10 2021
    • PCI DSS
    • PostgreSQL: Partitioning
    • PostgreSQL: Replication
    • Protobuf & gRPC
    • Redis: Streams
    • Resource Scaling
    • Signed URL
    • SOLID
    • Stack VS Heap
    • Stateful VS Stateless
  • Site Reliability Engineering
    • Chaos Engineering
    • Distributed Tracing
    • Kubernetes (k8s)
    • SLA, SLO, and SLI Metrics
    • Site Reliability Engineer
  • Others
    • FFMPEG Cheat sheet
Powered by GitBook
On this page
  • Summary
  • Scalar Types
  • Compound Type
  • primitive_types1.rs
  • primitive_types2.rs
  • primitive_types3.rs
  • primitive_types4.rs
  • primitive_types5.rs
  • primitive_types6.rs
  1. Rust
  2. Rustlings Exercises

Primitive Types

PreviousIfNextVectors

Last updated 4 months ago

Every value in Rust is of a certain data type, which tells Rust what kind of data is being specified so it knows how to work with that data.

References:

Summary

Scalar Types

A scalar type represents a single value. Rust has four primary scalar types:

  • Integer is a number without a fractional component.

  • Floating points: Rust has two primitive types for floating-point numbers (f32, f64), which are numbers with decimal points.

  • Character: char

    • We specify char literals with single quotes '.

    • Four bytes in size and represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII.

    • Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust.

  • Boolean type bool in Rust has two possible values: true and false. Booleans are one byte in size.

Compound Type

  • Tuple:

    • A tuple is a general way of grouping together a number of values with a variety of types into one compound type.

    • Tuples have a fixed length: once declared, they cannot grow or shrink in size.

  • Array:

    • Every element of an array must have the same type.

    • Unlike arrays in some other languages, arrays in Rust have a fixed length.

  • Slice:

    • Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.

    • A slice is a kind of reference, so it does not have ownership.

    • We create slices using a range within brackets by specifying [starting_index..ending_index], where starting_index is the first position in the slice and ending_index is one more than the last position in the slice.

primitive_types1.rs

fn main() {
    let is_morning = true;
    if is_morning {
        println!("Good morning!");
    }

    // Define a boolean variable with the name `is_evening` before the `if` statement below.
    // The value of the variable should be the negation (opposite) of `is_morning`.
    let is_evening = !is_morning;
    if is_evening {
        println!("Good evening!");
    }
}
  • In this exercise we only need to define variable is_morning that should be the opposite off is_evening.

  • We do it by using let is_evening = !is_morning;

primitive_types2.rs

fn main() {
    // Note the _single_ quotes, these are different from the double quotes
    // you've been seeing around.
    let my_first_initial = 'C';
    if my_first_initial.is_alphabetic() {
        println!("Alphabetical!");
    } else if my_first_initial.is_numeric() {
        println!("Numerical!");
    } else {
        println!("Neither alphabetic nor numeric!");
    }

    // TODO: Analogous to the example before, declare a variable called `your_character`
    // below with your favorite character.
    // Try a letter, try a digit (in single quotes), try a special character, try a character
    // from a different language than your own, try an emoji 😉
    // let your_character = '';
    let your_character = '😻';
    if your_character.is_alphabetic() {
        println!("Alphabetical!");
    } else if your_character.is_numeric() {
        println!("Numerical!");
    } else {
        println!("Neither alphabetic nor numeric!");
    }
}
  • In this exercise we can try what value char can represent.

  • Rust’s char type is four bytes in size and represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII.

  • Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust.

primitive_types3.rs

fn main() {
    // TODO: Create an array called `a` with at least 100 elements in it.
    // let a = ???
    let a = [1; 100];
    if a.len() >= 100 {
        println!("Wow, that's a big array!");
    } else {
        println!("Meh, I eat arrays like that for breakfast.");
        panic!("Array not big enough, more elements needed");
    }
}
  • In this exercise we need to initialize array with at least 100 in length.

  • Array in Rust have multiple ways of initialization.

    let a = [1, 2, 3, 4, 5];
    let b: [i32; 5] = [1, 2, 3, 4, 5];
    let c = [1; 100];
    1. Init all the value inside the square bracket [].

    2. Define the type and length [i32; 5].

    3. Initialize an array to contain the same value for each element by specifying the initial value, followed by a semicolon, and then the length of the array in square brackets [1; 100].

  • So we just need to use the last option to initialize array with same value with length 100 or more.

primitive_types4.rs

fn main() {
    // You can optionally experiment here.
}

#[cfg(test)]
mod tests {
    #[test]
    fn slice_out_of_array() {
        let a = [1, 2, 3, 4, 5];

        // TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes.
        // let nice_slice = ???
        let nice_slice = &a[1..4];
        assert_eq!([2, 3, 4], nice_slice);
    }
}
  • Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.

  • A slice is a kind of reference, so it does not have ownership.

  • We create slices using a range within brackets by specifying [starting_index..ending_index], where starting_index is the first position in the slice and ending_index is one more than the last position in the slice.

  • So in this exercise we only need to get value index 1 until 4 from array a.

    let nice_slice = &a[1..4];

primitive_types5.rs

fn main() {
    let cat = ("Furry McFurson", 3.5);

    // TODO: Destructure the `cat` tuple in one statement so that the println works.
    // let /* your pattern here */ = cat;
    let (name, age) = cat;
    println!("{name} is {age} years old");
}
  • In this exercise we need to extract the tuple variable.

  • To get the individual values out of a tuple, we can use pattern matching to destructure a tuple value, like this:

    let (name, age) = cat;

primitive_types6.rs

fn main() {
    // You can optionally experiment here.
}

#[cfg(test)]
mod tests {
    #[test]
    fn indexing_tuple() {
        let numbers = (1, 2, 3);

        // TODO: Use a tuple index to access the second element of `numbers`
        // and assign it to a variable called `second`.
        // let second = ???;
        let second = numbers.1;
        assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
    }
}
  • We can also access a tuple element directly by using a period (.) followed by the index of the value we want to access.

  • In this exercise we need to get second value from the tuple which is index 1 hence let second = numbers.1;.

Data Types
The Slice Type