Why can't I call `next_back()` on a `Split`?

The documentation for std::str::Split says that it implements std::iter::DoubleEndedIterator, which is supposed to have next_back() which will get the last element.

But when I do this

fn get_file_ext(file_name: &str) -> Option<String> {
  if let Some(ext) = file_name.split(".").next_back() {
    return Some(ext.to_owned());
  }
  None
}

I get the error

error[E0599]: no method named `next_back` found for type `std::str::Split<'_, &str>` in the current scope
   --> src/render.rs:194:43
    |
194 |   if let Some(ext) = file_name.split(".").next_back() {
    |                                           ^^^^^^^^^
    |
    = note: the method `next_back` exists but the following trait bounds were not satisfied:
            `std::str::Split<'_, &str> : std::iter::DoubleEndedIterator`

What does it mean by the following trait bounds were not satisfied?

The docs say specifically:

impl<'a, P> DoubleEndedIterator for Split<'a, P> where <P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,

That means Split is double-ended if, and only if, you use the right kind of pattern. &str isn't a DoubleEndedSearcher. Try char instead

1 Like

Try char instead

What would that look like?

split('.')

FWIW, the reason that str patterns aren't double-ended is that you could find different positions to match, particularly if the string contains any repetition. DoubleEndedIterator is supposed to produce the exact same items, just in reverse.

But there is rsplit when you really do want string matches in reverse.

1 Like

Oh so I could do file_name.rsplit(".").next() and that would be equivalent to file_name.split('.').next_back()?

1 Like

Yes, those should be the same.