2014-04-18 1 views
1

Основная цель - доступ к принадлежащей коробке, которая находится внутри кортежа, например. строка из (String, i32) в коде ниже.Заимствование из находящейся в собственности коробки внутри кортежа в ржавчине

Мое первое намерение состояло в том, чтобы использовать привязку let для заимствования из принадлежащей мне коробки. Заимствование работает для случая не кортежа (1), но не при использовании кортежа (2).

Я намерен ошибаться, и если да, есть ли еще один идиоматический способ доступа к строке?

Пример кода:

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); 
} 

Ошибка компилятора:

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

ответ

4

Ключевое слово ref используется для привязки по ссылке.

let (ref st_r, i) = st; 
+0

Обратите внимание, что когда вы это делаете, вы получаете 'st_r: & ~ str', а не' st_r: & str'. Вот почему 'as_slice()' необходимо в любом случае. Это можно проверить очень легко: 'println! (" {} ", St_r as int);' приводит к ошибке: нескалярный cast: & ~ str as int' –

+0

Вызов 'as_slice()' определенно важный часть ответа. В моем коде я в конечном итоге использовал эквивалент, если 'let (ref st_r, i) = st; let st_r = st_r.as_slice() '. Упоминание «int» еще два раза в подходе к сопоставлению оказалось немного избыточным. – sim82

2

Самый прямой путь, я считаю, является соответствие:

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

Обратите внимание, что я использовал ref s и s.as_slice() вместо s или &*s по двум причинам. Во-первых, &*s не допускается в связи с текущим специальным статусом ~str. Похоже, что когда DST изменится, это станет возможным. Во-вторых, я использовал ref s, потому что в противном случае первый компонент кортежа перемещается в s, и было бы невозможно вернуть ссылку на него изнутри тела match - он будет уничтожен, когда заканчивается match.

Нет такой проблемы с i, потому что int неявно может быть скопирован.

+0

Вы, вероятно, следует обновить этот вопрос Rust 1.0 и выше. – Shepmaster

0

Если вы заботитесь только о единственном значении кортежа, вы можете также использовать цифровые аксессоров (.0, .1, и так далее). Они могут иметь опорный оператор & применен к ним:

let st = ("blub".to_string(), 1); 
let st_r = &st.0;