How to create Vec<Option<T>> efficiently?


#1

I want to create a vector of Option:

let re: Vec<Option<i32>> = vec![Some(12), Some(21), Some(34), Some(...)]

Can I create it efficiently in the Rustic way without Some(..) repeatedly?


#2

You could do something like:

let re: Vec<Option<i32>> = vec![12, 21, 34 ...].iter()
    .map(|n| Some(n)).collect();

For a long list, this makes the source code shorter, but it is hardly more “efficient”, sine it requires run-time manipulation rather than static initialization.

If the list is long enough to be worth the trouble (or you have many of them), you could create a macro allowing you to write e.g.

let re: Vec<Option<i32>> = some_vec![12, 21, 34 ...];

That macro itself might look something like this (warning, untested):

macro_rules! some_vec {
    ($($item:expr),*) => {
        vec![ $( Some($item) ),* ]
    }
}

#3

Thank you


#4

You can also use .into_iter().map(Some).collect();


#5

@leonardo

It’s the first time that I saw this: .into_iter().map(Some).collect();

Official docs of core::iter::Iterator::map write:

Takes a closure and creates an iterator which calls that closure on each element.

so, as for map(Some), why does this work? Is Some a closure here?
Could you explain to me ? Thank you.


#6

Strictly speaking, map takes anything implementing FnMut. That can also be a function (functions may be seen as closures that don’t close over their environment).

Constructors like Some() can be used like functions, they implement FnMut.