Use <slice>::concat() to when having arrays instead of slices

Given the first two lets (where a1 and a2 are references to arrays, not slices), I'm searching for an easier way to join a1 and a2. I dislike having to write as &[_] in the following code:

fn main() {
    let a1 = &[1, 2, 3];
    let a2 = &[4, 5, 6];
    let b = [a1 as &[_], a2 as &[_]].concat();
    assert_eq!(b, vec![1, 2, 3, 4, 5, 6]);
}

(Playground)

I don't need that explicit unsized coercion (as it happens implicitly) in the following case:

fn main() {
    let a1 = &[1, 2, 3];
    let a2 = &[4, 5, 6];
    let mut b = Vec::with_capacity(a1.len() + a2.len());
    b.extend_from_slice(a1);
    b.extend_from_slice(a2);
    assert_eq!(b, vec![1, 2, 3, 4, 5, 6]);
}

(Playground)

But this second example is even more verbose. What's the best short way to concatenate a1 and a2 (which are of type &[i32, 3]) into a new Vec<i32>?

I'd convert the first array to a vector and extend it with the second one like this:

fn main() {
    let a1 = [1, 2, 3];
    let a2 = [4, 5, 6];
    
    let mut b = a1.to_vec();
    b.extend(a2);
    
    assert_eq!(b, vec![1, 2, 3, 4, 5, 6]);
}

Playground.

Not necessarily shorter than your first example, but without coercion.

I thought on that too, but doesn't this have a higher runtime cost, because a1.to_vec() doesn't know how long the final Vec will be?

For three elements the allocation time will hardly matter, but in theory you are right

You don't need to manually coerce all the elements. Just give enough context to the type inference.

let b = [&a1[..], a2].concat();
4 Likes

That's basically the same as:

let b = [a1 as &[_], a2].concat();

It's a bit shorter, yeah, but still feels somehow unwieldly (edit: and also unsymmetric).