В чем разница между приведением типов путем установки типа переменной и использованием `as`? - PullRequest
0 голосов
/ 06 июня 2019

В чем разница между этими двумя случаями? Почему закомментированная строка компилируется, а последняя строка в главном неверна?

Как вырезать строку (substr в C ++ с неконстантными аргументами) без дополнительной переменной?

use std::fs::File;
use std::io;
use std::io::Read;

fn read_string(filename: &str) -> Result<String, io::Error> {
    let mut s = String::new();
    File::open(filename)?.read_to_string(&mut s)?;
    Ok(s)
}

fn main() {
    let s = read_string("tt.txt").expect("Wow");

    // let s2: String = s.chars().skip(0).take(s.len() -2).collect();

    println!(
        "{}",
        s.chars().skip(0).take(s.len() - 2).collect() as String
    );
}

Ответы [ 2 ]

3 голосов
/ 06 июня 2019

Явно вводится переменная , а не приведение типа.

Как подробно объясняется в другом месте, Iterator::collect требует знания конкретного типа для сбора.

Приведение типов, например, выполняемое as, требует преобразования из одного типа в другой. Вы указали тип second (String), но компилятор все еще не может определить, каким должен быть тип first .

Turbofish

Синтаксис, который вы хотите использовать в сегодняшнем Rust, - turbofish :

use std::fs;

fn main() {
    let s = fs::read_to_string("tt.txt").expect("Wow");

    println!(
        "{}",
        s.chars().skip(0).take(s.len() - 2).collect::<String>()
    );
}

Тип Надпись

В качестве ночной функции вы также можете использовать экспериментальную надпись типа :

#![feature(type_ascription)]

use std::fs;

fn main() {
    let s = fs::read_to_string("tt.txt").expect("Wow");

    println!(
        "{}",
        s.chars().skip(0).take(s.len() - 2).collect(): String
    );
}

Другое

Вам не нужно писать read_string.

3 голосов
/ 06 июня 2019

Проблема заключается в методе .collect(). Из документации :

Поскольку collect() является настолько общим, это может вызвать проблемы с типом умозаключение. Таким образом, collect() - один из немногих случаев, когда вы Синтаксис, ласково известный как «TurboFish»: ::<>. Это помогает Алгоритм вывода понять, какую именно коллекцию вы пытаясь собрать в.

Компилятор не может определить тип коллекции, который вы хотите использовать, поэтому необходимо указать его явно.

Некоторые примеры:

fn main() {
    let s = String::from("magic");

    //different ways to specify the target type
    //1. -> explicitly declaring the variable type
    //2. -> turbofish syntax (great article about it: https://matematikaadit.github.io/posts/rust-turbofish.html)

    let a1: String = s.chars().skip(0).take(s.len() - 2).collect();
    let a2 = s.chars().skip(0).take(s.len() - 2).collect::<String>();

    let b1: Vec<char> = s.chars().skip(0).take(s.len() - 2).collect();
    let b2 = s.chars().skip(0).take(s.len() - 2).collect::<Vec<char>>();

    let c1: HashSet<char> = s.chars().skip(0).take(s.len() - 2).collect();
    let c2 = s.chars().skip(0).take(s.len() - 2).collect::<HashSet<char>>();
}

Как показывают примеры, многие целевые типы являются допустимыми, и компилятор не может решить, что вы хотели.

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