I want to write a function that would reverse a string and return a reference to the returned string. I thought I would be able to specify that the returned reference has the same lifetime as the provided reference.
fn reverse_string<'a>(input: &'a str) -> &'a str {
let res: &'a str = input.chars().rev().collect().as_slice();
res
}
This was my attempt, and I receive the error:
error[E0282]: type annotations needed
--> src/lib.rs:2:24
|
2 | let res: &'a str = input.chars().rev().collect().as_slice();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `B`
|
= note: type must be known at this point
I thought the type specification would resolve this. Lifetimes are a bit confusing to me, so I was hoping someone may be able to explain how to do this properly, or if I'm completely off base to begin with.
The lifetime issue is similar to The lifetime of &str makes comparison hard: if you create a new object, it's a new object, uncorrelated from the old one.
Therefore, you have two choices:
input.chars().rev().collect() for exampleinput in-place, which requires it to be mut of courseThe former looks easy:
fn reverse_new(input: &str) -> String {
input.chars().rev().collect()
}
however the String so created might be "flawed", because char (the intermediate type) are just Unicode code points not graphemes. As an example of Combining Characters imagine that you have [e, ́, o] in the original string, the ́ is attached to the e: éo, but after reversal you get [o, ́, e] where ́ is attached to the o: óe.
The latter is severely complicated by the fact that even ignoring graphemes issues, reversing UTF-8 in-place requires being UTF-8 aware to avoid splitting codepoints. Of course, one could simply create a reversed String and copy it into the input...
EDIT: I had initially thought of collecting into an intermediary Vec, but @AlexP realized it was unnecessary and one could collect directly into a String.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With