loops - 尝试在循环中更新 Option<&str> 时获得“借用时临时值下降”
问题描述
我正在尝试实现一个常用的模式——在下一个循环迭代中使用上一个循环迭代的结果。例如,要实现分页,您需要提供上一页最后一个值的 id。
struct Result {
str: String,
}
fn main() {
let times = 10;
let mut last: Option<&str> = None;
for i in 0..times {
let current = do_something(last);
last = match current {
Some(r) => Some(&r.str.to_owned()),
None => None,
};
}
}
fn do_something(o: Option<&str>) -> Option<Result> {
Some(Result {
str: "whatever string".to_string(),
})
}
但是,我不确定如何真正从循环中获取价值。目前,编译器错误是temporary value dropped while borrowed
(at &r.str.to_owned()
),虽然我做了很多其他尝试,但无济于事。
我发现真正让它工作的唯一方法是创建某种局部tmp_str
变量并像这样进行破解:
match current {
Some(r) => {
tmp_str.clone_from(&r.str);
last = Some(&tmp_str);
}
None => {
last = None;
}
}
但这并不像它应该做的那样。
解决方案
在您的代码中,仍不清楚被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
这种普遍的特征深深地内置在编译器中(?
-operator 等)。
后续问题: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
的似乎有点奇怪)。
推荐阅读
- sapui5 - sapui5 在 SAPUI5 中上传文件并在 odata 服务实体集中发送该文件
- javascript - 错误:无效的钩子调用,反应路由器历史
- inheritance - 试图应对 Java 中没有抽象变量的问题
- postgresql - Postgres序列值在插入记录后不增加
- elasticsearch - ES中如何只存储索引而不存储原文
- python - 尝试在电子邮件中嵌入通过 pyplot 创建的 png 文件时出现红十字
- javascript - 通过从动态 html (jquery) 中的数据中查找元素来获取 id
- svn - 如何在 Windows 10 中找到工作 svn 目录
- node.js - React - history.push 在数据获取后不起作用
- javascript - 选择列表选项的异步加载