Getting “temporary value dropped while borrowed” when trying to update an Option<&str> in a loop

前端 未结 2 897
隐瞒了意图╮
隐瞒了意图╮ 2021-01-05 06:00

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 n

2条回答
  •  长情又很酷
    2021-01-05 06:47

    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 = None;
    
        for _i in 0..times {
            last = do_something(&last).map(|r| r.str);
        }
    }
    
    fn do_something(_o: &Option) -> Option {
        Some(MyRes {
            str: "whatever string".to_string(),
        })
    }
    

    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).


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

    Both Option<&str> and Option 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. Here is a comparison of various methods:

    fn do_something(o: &Option) {
        let _a: Option<&str> = o.as_ref().map(|r| &**r);
        let _b: Option = o.clone();
    }
    fn do_something2(o: &Option<&str>) {
        let _a: Option<&str> = o.clone(); // do you need it?
        let _b: Option = o.map(|r| r.to_string());
    }
    fn do_something3>(o: &Option) {
        let _a: Option<&str> = o.as_ref().map(|s| s.as_ref());
        let _b: Option = o.as_ref().map(|r| r.as_ref().to_string());
    }
    
    fn main() {
        let x: Option = 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
    }
    

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

提交回复
热议问题