В вашем коде остается неясным, кем должен быть владелец String
, на который есть ссылка в last: Option<&str>
.Вы можете ввести дополнительную изменяемую локальную переменную, которой принадлежит строка.Но тогда у вас будет две переменные: владелец и ссылка, которые кажутся избыточными.Было бы намного проще сделать last
владельцем:
struct MyRes {
str: String,
}
fn main() {
let times = 10;
let mut last: Option<String> = None;
for _i in 0..times {
last = do_something(&last).map(|r| r.str);
}
}
fn do_something(_o: &Option<String>) -> Option<MyRes> {
Some(MyRes {
str: "whatever string".to_string(),
})
}
В do_something
вы можете просто передать весь аргумент по ссылке, это, скорее всего, будет тем, что вы хотели.Также обратите внимание, что называть собственную структуру Result
- плохая идея, потому что Result
- это такая распространенная черта, встроенная глубоко в компилятор (?
-оператор и т. Д.).
Дополнительный вопрос: Option<&str>
или Option<String>
?
Оба Option<&str>
и Option<String>
имеют различные компромиссы.Один лучше для передачи строковых литералов, другой лучше для передачи принадлежащих String
s.Я бы на самом деле предложил использовать ни один, и вместо этого сделать функцию универсальной по типу S
, который реализует AsRef<str>
.Вот сравнение различных методов:
fn do_something(o: &Option<String>) {
let _a: Option<&str> = o.as_ref().map(|r| &**r);
let _b: Option<String> = o.clone();
}
fn do_something2(o: &Option<&str>) {
let _a: Option<&str> = o.clone(); // do you need it?
let _b: Option<String> = o.map(|r| r.to_string());
}
fn do_something3<S: AsRef<str>>(o: &Option<S>) {
let _a: Option<&str> = o.as_ref().map(|s| s.as_ref());
let _b: Option<String> = o.as_ref().map(|r| r.as_ref().to_string());
}
fn main() {
let x: Option<String> = None;
let y: Option<&str> = None;
do_something(&x); // nice
do_something(&y.map(|r| r.to_string())); // awkward & expensive
do_something2(&x.as_ref().map(|x| &**x)); // cheap but awkward
do_something2(&y); // nice
do_something3(&x); // nice
do_something3(&y); // nice, in both cases
}
Обратите внимание, что не все из вышеперечисленных комбинаций очень идиоматичны, некоторые добавляются только для полноты (например, запрос AsRef<str>
, а затем создание собственного String
кажется немного странным).