🎓 A1Learner
🔍

Rust Mixed-Type Vectors

A mixed-type Vec is a Vec whose slots hold different shapes through one enum. Each slot holds the enum.

One type per slot refuses a mixed row

A Vec holds one type only, so this spreadsheet row is refused:

let row = vec![3, "blue"]; // error E0308: the items must all be one type

Wrap the choices in one enum

Every variant of an enum is the same type — the enum itself. So a Vec of the enum may hold a different shape in each slot:

enum Cell { Int(i32), Float(f64), Text(String) }
let row = vec![Cell::Int(3), Cell::Text(String::from("blue")), Cell::Float(10.12)];
println!("cells = {}", row.len());

Read each shape back with match

match looks inside one cell. The compiler checks that every variant has an arm — you cannot forget one:

let cell = Cell::Float(2.5);
match cell {
    Cell::Int(n) => println!("int {n}"),
    Cell::Text(s) => println!("text {s}"),
    Cell::Float(f) => println!("float {f}"),
}

Example

enum SpreadsheetCell { Int(i32), Float(f64), Text(String) }
fn main() {
    let row = vec![SpreadsheetCell::Int(3), SpreadsheetCell::Text(String::from("blue")), SpreadsheetCell::Float(10.12)];
    for cell in &row {
        match cell {
            SpreadsheetCell::Int(n) => println!("int {}", n),
            SpreadsheetCell::Text(s) => println!("text {}", s),
            SpreadsheetCell::Float(f) => println!("float {}", f),
        }
    }
}

Key points

  • Rust knows the size at compile time.
  • Each slot is as big as the biggest variant.
  • It also holds a small tag.
  • The tag says which variant it holds

In this example, SpreadsheetCell is an enum with three variants, one for each kind of cell. The Vec holds three cells, and every item is a SpreadsheetCell, so the one-type rule is kept. The for loop borrows each cell. match looks inside it. An Int prints its number. A Text prints its word. A Float prints its decimal. The output follows the row order: int 3, text blue, float 10.12.

Note

Use this trick when you know the full list of shapes in advance.

If the set of shapes is open-ended, a later tool (trait objects) fits better.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Why can a Vec<SpreadsheetCell> hold an Int, a Text and a Float?