Slices in Rust

use std::vec::Vec;

fn main() {
    // Unlike arrays, vectors are dynamically-sized.
    // An uninitialized vector is empty and has length 0.
    let mut s: Vec<String> = Vec::new();
    println!("uninit: {:?}, is_empty: {}, len: {}", s, s.is_empty(), s.len());

    // To create an empty vector with non-zero capacity, use
    // Vec::with_capacity. Here we create a vector of
    // Strings with capacity 3 (initially empty).
    s = Vec::with_capacity(3);
    println!("emp: {:?}, len: {}, cap: {}", s, s.len(), s.capacity());

    // We can push elements into the vector.
    s.push(String::from("a"));
    s.push(String::from("b"));
    s.push(String::from("c"));
    println!("set: {:?}", s);
    println!("get: {}", s[2]);

    // len returns the length of the vector as expected.
    println!("len: {}", s.len());

    // Vectors support pushing more elements.
    s.push(String::from("d"));
    s.extend(vec![String::from("e"), String::from("f")]);
    println!("apd: {:?}", s);

    // Vectors can be cloned.
    let c = s.clone();
    println!("cpy: {:?}", c);

    // Vectors support slicing with the syntax &vec[start..end].
    let l = &s[2..5];
    println!("sl1: {:?}", l);

    // This slices up to (but excluding) s[5].
    let l = &s[..5];
    println!("sl2: {:?}", l);

    // And this slices from (and including) s[2].
    let l = &s[2..];
    println!("sl3: {:?}", l);

    // We can declare and initialize a vector in a single line as well.
    let t = vec![String::from("g"), String::from("h"), String::from("i")];
    println!("dcl: {:?}", t);

    // Rust's standard library contains a number of useful
    // utility functions for vectors.
    let t2 = vec![String::from("g"), String::from("h"), String::from("i")];
    if t == t2 {
        println!("t == t2");
    }

    // Vectors can be composed into multi-dimensional data
    // structures. The length of the inner vectors can
    // vary, unlike with multi-dimensional arrays.
    let mut two_d = Vec::new();
    for i in 0..3 {
        let mut inner_vec = Vec::new();
        for j in 0..=i {
            inner_vec.push(i + j);
        }
        two_d.push(inner_vec);
    }
    println!("2d: {:?}", two_d);
}

This Rust code demonstrates the use of vectors, which are similar to slices in Go. Here are some key points:

  1. Rust uses Vec<T> for dynamic arrays, which is similar to slices in Go.
  2. We use Vec::new() to create an empty vector and Vec::with_capacity() to create a vector with a specific capacity.
  3. Elements are added to a vector using the push() method or extend() for multiple elements.
  4. Vectors in Rust support slicing with the &vec[start..end] syntax.
  5. Rust’s standard library provides many utility functions for vectors, similar to Go’s slices package.
  6. Multi-dimensional vectors can be created, allowing for varying lengths of inner vectors.

When you run this program, you’ll see output similar to the Go version, demonstrating the various operations on vectors.

Note that Rust’s ownership and borrowing rules apply to vectors, which can make some operations different from Go. For example, when we create a “copy” of a vector in Rust, we use clone() which creates a deep copy, unlike Go’s slice operations which can create views of the same underlying array.

$ cargo run
uninit: [], is_empty: true, len: 0
emp: [], len: 0, cap: 3
set: ["a", "b", "c"]
get: c
len: 3
apd: ["a", "b", "c", "d", "e", "f"]
cpy: ["a", "b", "c", "d", "e", "f"]
sl1: ["c", "d", "e"]
sl2: ["a", "b", "c", "d", "e"]
sl3: ["c", "d", "e", "f"]
dcl: ["g", "h", "i"]
t == t2
2d: [[0], [1, 2], [2, 3, 4]]

This example demonstrates how Rust’s vectors provide similar functionality to Go’s slices, with some differences due to Rust’s unique features like ownership and borrowing.