获得“借入时的暂时价值下降".尝试更新Option<& str>时循环 [英] Getting "temporary value dropped while borrowed" when trying to update an Option<&str> in a loop

查看:126
本文介绍了获得“借入时的暂时价值下降".尝试更新Option<& str>时循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一种常用的模式-在下一个循环迭代中使用上一个循环迭代的结果.例如,要实现分页,需要在上一页提供最后一个值的ID.

I'm trying to implement a commonly used pattern - using the result of a previous loop iteration in the next loop iteration. For example, to implement pagination where you need to give the id of the last value on the previous page.

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(位于&r.str.to_owned()),尽管我进行了许多其他尝试,但均无济于事.

However, I'm not sure how to actually get the value out of the loop. Currently, the compiler error is temporary value dropped while borrowed (at &r.str.to_owned()), though I made many other attempts, but to no avail.

我发现真正起作用的唯一方法是创建某种本地tmp_str变量并进行如下修改:

The only way I found to actually get it working is to create some sort of local tmp_str variable and do a hack like this:

match current {
    Some(r) => {
        tmp_str.clone_from(&r.str);
        last = Some(&tmp_str);
    }
    None => {
        last = None;
    }
}

但是,这并不像它应该做的那样.

But that doesn't feel like it's the way it's supposed to be done.

推荐答案

在您的代码中,仍不清楚应该是谁在last: Option<&str>中引用的String的所有者.您可以引入一个拥有该字符串的额外可变局部变量.但是然后您将有两个变量:所有者和引用,这似乎是多余的.只需将last设置为所有者,就会简单得多:

In your code, it remains unclear who the owner of the String referenced in last: Option<&str> is supposed to be. You could introduce an extra mutable local variable that owns the string. But then you would have two variables: the owner and the reference, which seems redundant. It would be much simpler to just make last the owner:

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中,您可以通过引用传递整个参数,这似乎更可能是您想要的.还要注意,命名自己的struct Result是一个坏主意,因为Result是内置于编译器(? -operator等)中的这种普遍特性.

In do_something, you can just pass the whole argument by reference, this seems more likely to be what you wanted. Also note that naming your own struct Result is a bad idea, because Result is such a pervasive trait built deeply into the compiler (?-operator etc).

后续问题:Option<&str>Option<String>?

Follow-up question: Option<&str> or Option<String>?

Option<&str>Option<String>都有不同的权衡.一种更好地传递字符串文字,另一种更好地传递拥有的String.我实际上建议不使用它们,而是使函数在实现AsRef<str>的类型S上通用.这里是各种方法的比较:

Both Option<&str> and Option<String> have different trade-offs. One is better for passing string literals, other is better for passing owned Strings. I'd actually propose to use neither, and instead make the function generic over type S that implements AsRef<str>. Here is a comparison of various methods:

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似乎有点奇怪).

Note that not all of the above combinations are very idiomatic, some are added just for completeness (e.g. asking for AsRef<str> and then building an owned String out of seems a bit strange).

这篇关于获得“借入时的暂时价值下降".尝试更新Option&lt;&amp; str&gt;时循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆