Lesson 6.1 · 8 min
A list: Vec
So far Chatterbox forgets every message the moment it handles it. To keep a conversation you need a list that grows. Rust's growable list is called Vec, and it follows the same one-owner rule you already know.
Adds to ChatterboxThe conversation history.
A list that grows
A Vec (said "vec", short for vector) is a list of values that all have the same type, and it can grow. You write the type as Vec<Message>: a Vec of Messages. The part in angle brackets says what is inside.
Think of it with the one-owner rule from chapter 4. The Vec owns every item in it. When the Vec goes away, its items go with it. Nobody else holds a copy.
$ cargo run
2 people
first is samVec::new() makes an empty list. When you already know the items, vec!["sam".to_string(), "ada".to_string()] makes a list with them in it: vec! is a macro (like println!) that builds a Vec from the items you list. push adds one item at the end, so the Vec has to be mut (you met mut in chapter 2). len() says how many items it holds. (Its answer, and any position you pass, has the type usize: a number that means "a position or a size".) names[0] reads the item at position 0: counting starts at zero, so the first item is number 0. In the next program, .clone() makes a second, separate copy of a String, so the function can hand one back while the list keeps its own.
What if the position is not there?
There are only two names in that list. What happens if you ask for position 5?
This program asks for position 5 of a two-item list. What happens?
- It compiles and runs
- It compiles, then panics
- Compile error E0308
Reveal the answer
It compiles, then panics at run time. The program compiles, because the compiler cannot know how long the list is at run time. When it runs, position 5 does not exist, so the program stops with a panic: "index out of bounds". Reading by [ ] is a promise that the item is there. If you break the promise, the program crashes.
The polite way: get
A chat program receives messages from other people, so "position 5 does not exist" is a normal thing to meet, not a bug. For those cases a Vec has get. It does not crash. It returns an Option (lesson 5.4): Some(item) when the position exists and None when it does not.
Use [ ] when you have just checked the length or the position is certain. Use get whenever it might be missing.
$ cargo run
Some("ada")
NoneChatterbox v0.6: it remembers
Now give Chatterbox a history. Make an empty Vec<Message> before the loop. Every time someone says something, build a Message and push it. The Vec takes ownership of the message, so there is nothing else to tidy up. At the end, report how many messages it holds and use get(0) to look at the first one, because there might not be one.
The highlighted lines are the new ones. For now every message comes from the same user, "sam". Several users come two lessons from now.
$ cargo run
commands: /help /say /quit
saved message 1
saved message 2
unknown command: /bogus
history has 2 messages
first: hello thereWrite last_text. It returns Some(text) of the newest message (the one at the end of the Vec), or None if the history is empty. It must never crash.
Write last_text. It returns Some(text) of the newest message (the one at the end of the Vec), or None if the history is empty. It must never crash.
Hidden tests (3): empty_history_has_no_last_text newest_is_the_last_one_pushed single_message
This exercise runs real Rust in your browser through the official Rust Playground, so it needs JavaScript.
What you have now
Chatterbox keeps a Vec<Message>. You can push, count, index and get. The list owns its messages, and a missing position is something you handle, not something you hope never happens. Next you will walk through the list instead of picking one position at a time.
Say it out loud, then reveal
What is the difference between names[5] and names.get(5) on a two-item Vec?Reveal
Why does the Vec need to be mut before you push?Reveal
Who owns the Messages you push?Reveal
That is lesson 6.1. Tick it off so the course remembers where you are.
Questions people ask
What does Vec stand for in Rust?
Vec is short for vector: a growable list of values that all have the same type.
Is a Rust Vec the same as a Python list?
It is the closest match, but every item must be the same type, and reading past the end panics instead of raising an exception you can catch in the usual way.
How do I make a Vec with items already in it?
Use the vec! macro, for example vec![1, 2, 3].