`FromIterator<Cow<'_, &str>>` is not implemented for `String`

I want to do this:

["a", "b", "c"]
    .iter()
    .map(|s| {
        if s == &"b" {
            Cow::Owned(format!(r"\\{s}"))
        } else {
            Cow::Borrowed(s)
        }
    })
    .collect::<String>();

But it doesn't seem possible. Because of a missing impl... Is this a good contribution to the std lib?

I'm also getting another error though:

error[E0271]: type mismatch resolving `<&str as ToOwned>::Owned == String`
 --> src/main.rs:7:17
  |
7 |                 Cow::Owned(format!(r"\\{s}"))
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `String`

Why would it expect &str... And find Sring?? Shouldn't it be finding Cow?

Thank you!

Normally you have Cow<str>, but you have Cow<&str>, which means Borrowed holds &&str and Owned holds &str. You need to remove a reference.

let s = ["a", "b", "c"]
    .iter()
    .map(|&s| {
        if s == "b" {
            Cow::Owned(format!(r"\\{s}"))
        } else {
            Cow::Borrowed(s)
        }
    })
    .collect::<String>();

This happens because your array is [&str; 3] and iter creates references of the items, so &&str.

You could also consume the array:

let s = ["a", "b", "c"]
    .into_iter()
    .map(|s| {
        if s == "b" {
            Cow::Owned(format!(r"\\{s}"))
        } else {
            Cow::Borrowed(s)
        }
    })
    .collect::<String>();
3 Likes

Just deref s on the borrowed case. You can see it from the list of impls suggested.

Cow::Borrowed(*s)
1 Like

Alternately, replace .iter() with .into_iter() or .iter().copied():

    ["a", "b", "c"]
        .into_iter()
        .map(|s| {
            if s == "b" {
                Cow::Owned(format!(r"\\{s}"))
            } else {
                Cow::Borrowed(s)
            }
        })
        .collect::<String>();
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.