Как использовать вектор срезов строк - PullRequest
3 голосов
/ 28 июня 2019

Мне интересно, почему это работает

fn main() {
    let v: Vec<&str> = Vec::new();
    let s: &str = v.get(0).unwrap();
    let new_string = String::from(s);
    println!("{}", new_string);
}

но не этот:

fn main() {
    let v: Vec<&str> = Vec::new();
    let s = v.get(0).unwrap();
    let new_string = String::from(s);
    println!("{}", new_string);
}

Я получаю следующую ошибку из второго фрагмента:

let new_string = String::from(s);
                  ^^^^^^^^^^^^ the trait `std::convert::From<&&str>` is not implemented for `std::string::String`

1 Ответ

0 голосов
/ 28 июня 2019

Метод Vec::<T>::get() возвращает Option<&T>, то есть опцию ссылки на вектор. Поскольку ваш вектор уже содержит ссылки (&str), это означает, что get() в вашем случае возвращает Option<&&str>.

Итак, причина, по которой ваш первый пример компилируется, заключается в том, что, явно указав тип переменной s, вы вызываете разыменование coercion , то есть компилятор автоматически вставляет оператор разыменования :

// You write this:
let s: &str = v.get(0).unwrap();

// Compiler actually does this:
let s: &str = *v.get(0).unwrap();

Тогда, поскольку существует реализация признака From<&str> для String, компилятор принимает вызов String::from(s).

Однако во втором фрагменте без явной аннотации типа тип, назначенный для s, равен &&str:

let s: &&str = v.get(0).unwrap();

Это меняет ситуацию с методом String::from(): для String нет реализации From<&&str>, и компилятор не может скомпилировать код.

Логичный вопрос здесь заключается в том, почему в этом случае не происходит разглашение, когда в качестве аргумента для from() используется s? Ответ заключается в том, что принудительное приведение не происходит для универсальных методов, и String::from является универсальным методом, потому что он опирается на параметр типа признака From. Компилятор не может выполнить принудительное приведение, потому что вполне возможно (в принципе) иметь методы From<&str> и From<&&str>, которые потенциально могут выполнять разные действия.

Даже если From<&&str> сейчас не существует, и компилятор применил бы принудительное приведение, это сделало бы код хрупким по отношению к будущей эволюции: если по какой-то причине From<&&str> будет добавлено в будущую версию стандартной библиотеки ваш код может молча сломаться, потому что теперь он будет вызывать другой метод, чем раньше, с потенциально другой логикой.

(Естественно, я не говорю, что From<&&str> действительно будет добавлено в будущую версию libstd; это общие рассуждения, применимые к любому типу признаков, в любой кодовой базе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...