The ref
keyword is used to bind by reference.
let (ref st_r, i) = st;
Pregunta
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, _)`
Solución
The ref
keyword is used to bind by reference.
let (ref st_r, i) = st;
Otros consejos
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.
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;