Why do I get "no method named `join` found for type `[usize]` in the current scope"?

Viewed 2910
fn example(books: Vec<usize>, n_books: usize) {
    let fbooks = books[0..n_books].join(" ");
}
error[E0599]: no method named `join` found for type `[usize]` in the current scope
 --> src/lib.rs:2:36
  |
2 |     let fbooks = books[0..n_books].join(" ");
  |                                    ^^^^ method not found in `[usize]`

I tried mapping usize to String, collecting into Vec and some more random stuff. I don't understand what's going on.

1 Answers

TLDR:
Since map() transforms one iterator into another iterator, you should provide an iterator first.
Try this:

fn example(books: Vec<usize>, n_books: usize) -> String {
    books[0..n_books]
        .iter()
        .map(|u| u.to_string())
        .collect::<Vec<_>>()
        .join(" ")
}
fn main() {
    let books: Vec<usize> = vec![1, 2, 3];
    let n_books: usize = 2;
    let result = example(books, n_books);
    println!("{}", result); //"1 2"
}

Notes:
You should not join the usize vector items with &str type. You need to convert usize to string first then join it:

map(|u| u.to_string())

The standard library's join is defined only for slices, so the following code works:

let books: &[_] = &["1", "2", "3"];
let n_books: usize = 2;
let result = books[0..n_books].join(" ");
println!("{}", result); // "1 2"

Edit:
From your comment:

What's the difference using take(n) or a subscript operator (re-slicing books[0..n_books])

A slice is a type composed of a length and a pointer to a memory.
You may use .take(n_books) instead of re-slicing, which is an iterator that only iterates over the first n iterations of iter, try this:

    let books: Vec<usize> = vec![1, 2, 3];
    let n_books: usize = 2;
    let result = books
        .iter()
        .take(n_books)
        .map(|u| u.to_string())
        .collect::<Vec<_>>()
        .join(" ");

    println!("{}", result); //"1 2"
Related