Tuples and Arrays

1. Welcome and Icebreaker:

Welcome back!

If you could combine any two existing data types (like integers, booleans, etc.) into a new, custom compound type, what would you choose, and what kind of real-world object or concept could you represent with it?

2. Outline the Session:

Here’s what we’ll cover:

  1. Concept Explanation: We’ll discuss the characteristics, syntax, and use cases of tuples and arrays. We’ll highlight the key differences between them.
  2. Live Coding Demonstration: We’ll write code examples to demonstrate how to create, access, and manipulate tuples and arrays.
  3. Tasks: I will challenge you in task section.

Learning Outcomes: By the end of this session, you will be able to:

  • Create and initialize tuples and arrays.
  • Access individual elements within tuples and arrays.
  • Understand the differences between tuples and arrays, and when to use each.
  • Destructure tuples.
  • Iterate over arrays.
  • Understand array slicing (getting a portion of an array).

Expectations: As always, ask questions! Experimenting with the code is key to understanding these concepts.

3. Concept Explanation:

Tuples:

  • Fixed Size: Once a tuple is created, its size (the number of elements) cannot change.
  • Heterogeneous: The elements in a tuple can be of different data types. For example, a tuple can hold an integer, a string, and a boolean all at once.
  • Ordered: The elements in a tuple have a specific order, and you access them by their position (index), starting from 0.
  • Syntax: Tuples are created using parentheses () and separating the elements with commas ,.

Arrays:

  • Fixed Size: Like tuples, arrays have a fixed size that cannot be changed after creation.
  • Homogeneous: All elements in an array must be of the same data type.
  • Ordered: Elements are accessed by their index (position), starting from 0.
  • Syntax: Arrays are created using square brackets [] and separating the elements with commas ,. The type signature for an array is [T; N], where T is the data type of the elements and N is the number of elements (the size).

Key Differences Summarized:

Feature Tuple Array
Size Fixed Fixed
Element Types Can be different (heterogeneous) Must be the same (homogeneous)
Use Case Grouping related values of different types Storing a collection of items of the same type

4. Live Coding Demonstration:

fn main() {
    // --- Tuples ---

    // Creating a tuple
    let person: (&str, i32, bool) = ("Alice", 30, true);

    // Accessing tuple elements by index
    let name = person.0;
    let age = person.1;
    let is_active = person.2;
    println!("Name: {}, Age: {}, Active: {}", name, age, is_active);

    // Destructuring a tuple
    let (name, age, is_active) = person; // Same as above, but more concise
    println!("Name: {}, Age: {}, Active: {}", name, age, is_active);

    // Tuple with mixed types
    let mixed_tuple = (42, "hello", 3.14, false);

    // --- Arrays ---

    // Creating an array
    let numbers: [i32; 5] = [1, 2, 3, 4, 5]; // Array of 5 i32 integers

    // Accessing array elements by index
    let first = numbers[0];
    let second = numbers[1];
    println!("First: {}, Second: {}", first, second);

    // Array with default values
    let default_array = [0; 10]; // Creates an array of 10 elements, all initialized to 0

    // Iterating over an array using a for loop
    for number in numbers.iter() {
        println!("Number: {}", number);
    }

    // Iterating with index
    for i in 0..numbers.len() {
        println!("Number {}: {}",i, numbers[i]);
    }
    // Array slicing
    let slice = &numbers[1..4]; // Creates a slice containing elements at index 1, 2, and 3
    println!("Slice: {:?}", slice); // Use {:?} for debugging print of arrays and slices

    //  slice with for
    for item in slice{
        println!("Slice Item: {}",item)
    }

    // Mutating array elements (only if the array is declared as mutable)
    let mut mutable_array = [1, 2, 3];
    mutable_array[0] = 10;
    println!("Mutable array: {:?}", mutable_array);

    // Out-of-bounds access (this will cause a panic at runtime!)
    // let out_of_bounds = numbers[10]; // Uncommenting this line will cause an error
}

Key takeaways from the code:

  • Tuple Creation: We create tuples with parentheses and commas: ("Alice", 30, true).
  • Tuple Access: We access tuple elements using dot notation and the index: person.0.
  • Tuple Destructuring: We can unpack a tuple into separate variables: let (name, age, is_active) = person;.
  • Array Creation: We create arrays with square brackets and commas: [1, 2, 3, 4, 5]. The type signature is [i32; 5].
  • Array Access: We access array elements using square brackets and the index: numbers[0].
  • Array Iteration: We can use a for loop with .iter() to iterate over the elements of an array, or use range.
  • Array Slicing: We create array slice by & with range.
  • Mutability: Arrays must be declared as mut to modify their elements.
  • Runtime Errors: Accessing an array element with an out-of-bounds index will cause a panic (a runtime error) in Rust. This is a safety feature of Rust.

5. Tasks

  1. Tuple Swap: Create a tuple containing two values. Write code to swap the values within the tuple (you might need to use destructuring and create a new tuple).
  2. Array Initialization: Create an array of f64 values with a length of 7. Initialize all elements to the value 2.71828 (Euler’s number).
  3. Array Filtering: Create an array of integers. Write code to iterate through the array and print only the even numbers.
  4. Tuple of Arrays: Create a tuple where one element is an array of integers and another element is an array of strings. Access and print elements from both arrays within the tuple.
  5. Array Slicing: Create an array of at least 10 elements. Create a slice that contains the elements from index 3 up to (but not including) index 7. Print the slice. Then, create another slice that contains the last 3 elements of the array.
  6. Find the Maximum: Create an array of i32 values. Write code to find and print the maximum value in the array (without using any built-in max function). You’ll need to use a loop and a variable to keep track of the current maximum.