4

I use to have extensive use of Vec<&str>, but someone on Discord talked me into changing that to &[&str], however in some cases this has produced problems. Take for example this code which used to work,

fn main() { 
  let pos: Vec<String> = vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()];
  let pos: Vec<&str> = pos.iter().map(AsRef::as_ref).collect(); 
}

When I change that second line to

let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect(); 

I get the error,

error[E0277]: a value of type `&[&str]` cannot be built from an iterator over elements of type `&_`
 --> bin/seq.rs:3:51
  |
3 |     let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect();    
  |                                                      ^^^^^^^ value of type `&[&str]` cannot be built from `std::iter::Iterator<Item=&_>`
  |
  = help: the trait `FromIterator<&_>` is not implemented for `&[&str]`

How can I convert a Vec<String> into a &[&str]. I got this method from this answer on StackOverflow, which I tried to port to &[&str] with no luck.

8
  • Have you tried? let pos:&[&str] = &pos.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..] Commented Oct 12, 2021 at 6:22
  • you can trivially use a &Vec<T> as a &[T], there's a deref-coercion for it, but you need to .collect() into a Vec. Commented Oct 12, 2021 at 6:22
  • 1
    The advice you received sounds like it was either given or taken haphazardly, perhaps the reasoning was similar to this? Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument? Commented Oct 12, 2021 at 6:27
  • @kmdreko If I try collecting into a vec and passing that in I get the trait From<&Vec<&str>> is not implemented for PositionalArgs<'_> Commented Oct 12, 2021 at 6:36
  • 1
    Please check the as_slice, it does the same thing(playground). And for the github issue, please be careful, that code is not correct, you are missing & while getting slice Commented Oct 12, 2021 at 7:22

1 Answer 1

6

A simple way is to use .as_slice()

let pos: Vec<String> = vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()];
let pos: Vec<&str> = pos.iter().map(AsRef::as_ref).collect();

let pos: &[&str] = pos.as_slice();

But, perhaps a better solution exist


Sign up to request clarification or add additional context in comments.

2 Comments

Great answer thanks a ton! If someone has a better answer, I'll accept it instead, but this is working for me.
Juste about the alternative proposition in github, "let pos: &[&str] = pos.iter().map(AsRef::as_ref).collect::<Vec<_>>().as_slice();". This compile but not work. If you try to use pos it, i.e. "dbg!(pos)", get "error[E0716]: temporary value dropped while borrowed".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.