1

The main goal is to access an owned box that is inside a tuple, e.g. the string from the (String, i32) in the code below.

My first intention was to use a let binding to borrow from the owned box. Borrowing works for the non-tuple case (1), but not when a tuple is involved (2).

Is my intention wrong, and if so, is there another idiomatic way to access the string?

Example code:

fn main() {
    // 1. Normal borrowing
    let s: String = "blub".to_string();
    let sr: &str = &s; // this works

    // 2. Borrowing from a tuple
    let st = ("blub".to_string(), 1);
    let (st_r, i): (&str, i32) = st; // error: mismatched types:

    println!( "{} {} {} {}", s, sr, st_r, i);
}

The compiler error is:

error: mismatched types:
 expected `(&str, i32)`,
    found `(collections::string::String, _)`
4

3 回答 3

5

The ref keyword is used to bind by reference.

let (ref st_r, i) = st;
于 2014-04-18T19:00:42.517 回答
2

The most direct way, I believe, is matching:

let st = (~"blub", 1i);
let (st_r, i) = match st {
    (ref s, i) => (s.as_slice(), i)
};
println!("{} {}", st_r, i);

Note that I used ref s and s.as_slice() instead of s or &*s for two reasons. First, &*s is not allowed due to current special status of ~str type. It seems that it will be possible when DST change lands. Second, I used ref s because otherwise first tuple component is moved into s, and it wouldn't be possible to return a reference to it from inside of match body at all - it will be destroyed when match ends.

There is no such problem with i because int is implicitly copyable.

于 2014-04-18T17:33:45.563 回答
0

If you only care about a single value of the tuple, you can also use the numeric accessors (.0, .1, and so on). These can have the reference operator & applied to them:

let st = ("blub".to_string(), 1);
let st_r = &st.0;
于 2016-03-17T13:37:48.293 回答