CodeBlanks Logo Icon CodeBlanks

Generic stack

Build a Vec-backed generic Stack<T> data structure.

Final task: generic stack

In the intermediate level's final tasks you'll combine generics, traits, iterators and error handling. The first: a stack that works with any type. Last in, first out (LIFO):

struct Yigin<T> {
    ogeler: Vec<T>,
}

impl<T> Yigin<T> {
    fn new() -> Self { .. }
    fn push(&mut self, x: T) { .. }
    fn pop(&mut self) -> Option<T> { .. }      // None if empty
    fn peek(&self) -> Option<&T> { .. }        // look without removing
    fn len(&self) -> usize { .. }
    fn is_empty(&self) -> bool { .. }
}

peek returns a reference, so T doesn't need to be Clone.

Delegating to Vec

Stack behaviour matches Vec's methods one to one; the wrapper only narrows the API and gives meaningful names:

impl<T> Yigin<T> {
    fn push(&mut self, x: T) { self.ogeler.push(x); }
    fn pop(&mut self) -> Option<T> { self.ogeler.pop() }
    fn peek(&self) -> Option<&T> { self.ogeler.last() }
}

The user can't insert into the middle of the vector; the stack's invariants are protected.

Practice Stack

Write the Yigin<T> type above with all its methods. Push 1, 2, 3; print the results of pop(), peek(), len() and is_empty() for an empty Yigin<&str> on one line.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
struct Yigin<T> {
    ogeler: Vec<T>,
}

impl<T> Yigin<T> {
    fn new() -> Self {
        Self { ogeler: Vec::new() }
    }
    fn push(&mut self, x: T) {
        self.ogeler.push(x);
    }
    fn pop(&mut self) -> Option<T> {
        self.ogeler.pop()
    }
    fn peek(&self) -> Option<&T> {
        self.ogeler.last()
    }
    fn len(&self) -> usize {
        self.ogeler.len()
    }
    fn is_empty(&self) -> bool {
        self.ogeler.is_empty()
    }
}

fn main() {
    let mut y = Yigin::new();
    for n in [1, 2, 3] {
        y.push(n);
    }
    let p = y.pop();
    let t = y.peek().copied();
    let bos: Yigin<&str> = Yigin::new();
    println!("{:?} {:?} {} {}", p, t, y.len(), bos.is_empty());
}

Expected output

Some(3) Some(2) 2 true

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Which <code>Vec</code> method is used for <code>peek</code>?

  • get(0)
  • last() Correct answer
  • first()
  • pop()

Explanation: The top of the stack is the end of the vector; last() gives Option<&T> to the last element.

2 Look at the top

Question
fn peek(&self) -> Option<&T> {
    self.ogeler.____()
}
Answer
fn peek(&self) -> Option<&T> {
    self.ogeler.last()
}

Explanation: last gives a reference to the last element.

3 Operation and result (1, 2, 3 pushed)

Term Meaning
pop() Some(3)
then peek() Some(2)
then len() 2
Yigin::<&str>::new().is_empty() true

All lessons in Intermediate